2016-11-17 2 views
3

Я получаю следующее сообщение об ошибке:T-SQL Агрегатная функция подзапрос

Cannot perform an aggregate function on an expression containing an aggregate or a subquery. 

С помощью этого кода:.

SELECT 
    loc.Location 
    ,COUNT(CASE 
     WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'XYZ') 
      THEN 1 
      ELSE NULL 
     END) AS XYZ_Trainee_Count 
    ,COUNT(CASE 
     WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'ABC') 
      THEN 1 
      ELSE NULL 
     END) AS ABC_Trainee_Count 

FROM 
    dbo.n_HRODS hr INNER JOIN dbo.Locations loc 
     ON loc.LocationID = hr.LocationID 
    INNER JOIN dbo.EmpData dat 
     ON dat.EmpID = hr.EmpID 

WHERE dat.Trainee = 1 

GROUP BY loc.Location 

DBO [Заголовки] представляет собой вид, что объединяет две колонны из двух других таблиц. Я в основном делаю это так, потому что программист передо мной сделал что-то вроде этого:

,COUNT(CASE 
    WHEN SAC in (lists about 30 items) 
     THEN 1 
     ELSE NULL 
    END) 

Очевидно, что я не хочу, чтобы перечислить 30 пунктов в этом случае заявление ... и когда эти элементы изменяются по каким-либо разум через 3 года, то кто будет помнить, чтобы вернуться в этот код и обновил эти пункты? Никто ...

Заранее за вашу помощь.

ответ

2

Вы можете сделать это с парой дополнительных LEFT OUTER JOINs к этой title таблице:

SELECT 
    loc.Location 
    ,COUNT(CASE WHEN titles1.[SAC] IS NOT NULL THEN 1 ELSE NULL END) AS XYZ_Trainee_Count 
    ,COUNT(CASE WHEN titles2.[SAC] IS NOT NULL THEN 1 ELSE NULL END) AS ABC_Trainee_Count 

FROM 
    dbo.n_HRODS hr INNER JOIN dbo.Locations loc 
     ON loc.LocationID = hr.LocationID 
    INNER JOIN dbo.EmpData dat 
     ON dat.EmpID = hr.EmpID 
    LEFT OUTER JOIN dbo.[Titles] titles1 
     ON titles1.[title]='XYZ' AND 
      hr.SAC = titles1.[SAC] 
    LEFT OUTER JOIN dbo.[Titles] titles2 
     ON titles2.[title]='ABC' AND 
      hr.sac = titles2.[SAC]  
WHERE dat.Trainee = 1  
GROUP BY loc.Location 

В качестве альтернативы, если вы на самом деле замужем за те подзапросы в вашем ЗЕЬЕСТЕ, поскольку фактический запрос является большим кошмаром и подумал о monkeying с стыками достаточно, чтобы сделать вас слабыми, то вы можете просто удалить агрегацию из этого запроса и засунуть все это в подзапрос до агрегирования:

SELECT location, count(XYZ_Trainee) AS XYZ_Trainee_Count, count(ABC_Trainee) as ABC_Trainee 
FROM 
(
    SELECT 
     loc.Location 
     ,CASE 
      WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'XYZ') 
       THEN 1 
       ELSE NULL 
      END AS XYZ_Trainee 
     ,CASE 
      WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'ABC') 
       THEN 1 
       ELSE NULL 
      END AS ABC_Trainee 

    FROM 
     dbo.n_HRODS hr INNER JOIN dbo.Locations loc 
      ON loc.LocationID = hr.LocationID 
     INNER JOIN dbo.EmpData dat 
      ON dat.EmpID = hr.EmpID 

    WHERE dat.Trainee = 1 
) sub 
GROUP BY location 

Я бы стремиться к первому хотя, поскольку это будет легче поддерживать и, вероятно, получить лучший путь выполнения от вашей РСУБД и быстрее работать в результате. Хотя ... это просто догадка.

+0

Большое спасибо за помощь! – blacksaibot

2

Очень похоже на первый ответ JNevill. Но если вы присоединитесь к заголовку один раз, вы можете проверить и подсчитать количество требуемых номеров.

SELECT 
    loc.Location 
    ,COUNT(CASE WHEN t.[title] = 'XYZ' THEN 1 END) AS XYZ_Trainee_Count 
    ,COUNT(CASE WHEN t.[title] = 'ABC' THEN 1 END) AS ABC_Trainee_Count 

FROM 
    dbo.[n_HRODS] hr 
INNER JOIN dbo.[Locations] loc 
     ON loc.LocationID = hr.LocationID 
INNER JOIN dbo.[EmpData] dat 
     ON dat.EmpID = hr.EmpID 
INNER JOIN dbo.[Titles] t 
     ON hr.SAC = t.[SAC]  
WHERE dat.Trainee = 1 

GROUP BY loc.Location  
+0

Ах, интересно. Спасибо за информацию! – blacksaibot

Смежные вопросы