#sql #sql-server #tsql
#sql #sql-сервер #tsql
Вопрос:
SELECT l.LocID, COUNT(ulr.UserID)
FROM Locations l
LEFT OUTER JOIN UserLocationRights ulr ON l.LocID = ulr.LocID
LEFT OUTER JOIN Devices d ON l.LocID = d.LocID
LEFT OUTER JOIN UserModelRights umr ON d.ModelName = umr.ModelName
AND ulr.UserID = umr.UserID
GROUP BY l.LocID, ulr.UserID, d.ModelName
ORDER BY l.LocID, ulr.UserID
Я хочу, чтобы результатами были LocID
все записи в Locations
, а во втором столбце было количество пользователей, имеющих права на это местоположение, которые также имеют права хотя бы на один из Devices
in Location
, который определяется записями в UserModelRights
.
Я могу только понять, как получить то, что я хочу, вот так:
SELECT l.LocID, IsNull(UserHasModelRightInLoc.UserCount, 0) UserCount
FROM Locations l
LEFT OUTER JOIN (
SELECT ulr.LocID, COUNT(UserModelRightsPerLocation.UserID) UserCount
FROM UserLocRights ulr
INNER JOIN (
SELECT l.LocID, umr.UserID
FROM UserModelRights umr
INNER JOIN Devices d ON umr.ModelName = d.ModelName
INNER JOIN Locations l ON d.LocID = l.LocID
GROUP BY umr.ModelName, umr.UserID, l.LocID
) UserModelRightsPerLocation ON ulr.LocID = UserModelRightsPerLocation.LocID
AND ulr.UserID = UserModelRightsPerLocation.UserID
GROUP BY ulr.LocID
) UserHasModelRightInLoc ON l.LocID = UserHasModelRightInLoc.LocID
ORDER BY l.LocID
Я не знаю, возможно ли это, но я предполагаю, что может быть способ GROUP BY
получить то, что я хочу, используя мой первый, гораздо меньший запрос. Проблема в том, что я думаю, что мне нужно выполнить несколько GROUP BY
в определенном порядке, и я не знаю, возможно ли это или имеет смысл в SQL.
Есть ли способ получить желаемый результат без использования агрегатной функции? Если нет, может быть, сузить его до одного?
Комментарии:
1. Можете ли вы показать образцы данных и желаемые результаты? Просто перепроектировать ваш запрос, чтобы написать другую версию, перебросить его через стену и угадать, по-прежнему ли он дает правильные результаты, будет утомительно.
2. Нет, невозможно ПОДСЧИТАТЬ без использования агрегатной функции, и зачем вам это нужно?
3. Как ожидать агрегирования без агрегированной функции?
4.
"there's no way to COUNT without using an aggregate function"
: Это неверно @TabAlleman. Возможно, агрегат — лучшее решение, но вы можете РАССЧИТЫВАТЬ, используя множество других вариантов. Например, используя ROW_NUMBER() или функции ранжирования с TOP 1. Опять же, я не говорю, что это правильное решение, но только то, что ПОДСЧЕТ может быть выполнен без агрегата.5. @Eric, я прокомментировал не вопрос, а неверное предположение, что вы должны использовать агрегатную функцию для ПОДСЧЕТА. Как только OP предоставит DDL DML, я отвечу на этот вопрос… ПОДСЧЕТ без агрегата:
DECLARE @T TABLE (x int); INSERT @T(x) VALUES (2),(5),(7),(6); WITH MyCTE as (SELECT RN = ROW_NUMBER() OVER (ORDER BY x DESC) FROM @T) SELECT TOP 1 RN FROM MyCTE ORDER BY RN DESC
Ответ №1:
Я нахожу это немного сложным для понимания без выборки данных. Но, основываясь на вашем описании, это может сделать то, что вы хотите:
SELECT l.LocID, COUNT(DISTINCT ulr.UserID)
FROM Locations l LEFT JOIN
UserLocationRights ulr
ON l.LocID = ulr.LocID LEFT JOIN
Devices d
ON l.LocID = d.LocID LEFT JOIN
UserModelRights umr
ON d.ModelName = umr.ModelName AND
ulr.UserID = umr.UserID
GROUP BY l.LocID
ORDER BY l.LocID;
Комментарии:
1. Это звучит очень близко к тому, что я пытался сделать, если не совсем точно. Единственная проблема в том, что я получаю разные значения, чем мой запрос в моей операционной системе, когда возвращаются агрегатные функции, и я пока не уверен, почему…
2. Я получил результаты для сопоставления, изменив его на это:
SELECT l.LocID, COUNT(DISTINCT ulr.UserID) FROM LocStruct l LEFT JOIN Devices d ON l.LocID = d.LocID LEFT JOIN UserModelRights umr ON d.ModelName = umr.ModelName LEFT JOIN UserLocRights ulr ON l.LocID = ulr.LocID AND ulr.UserID = umr.UserID GROUP BY l.LocID ORDER BY l.LocID;