Можете ли вы объединить операторы case и top, чтобы указать, какие значения находятся в нескольких верхних (Microsoft SQL)

#sql #sql-server #tsql

#sql #sql-server #tsql

Вопрос:

У меня есть список сборов для обобщения, где каждая плата используется повторно с течением времени. Мой проект заключается в суммировании стоимости каждой платы за год и обозначении того, какие из них входят в топ-80 по значению, а какие нет. Мне нужны два столбца, один с кодом платы, а другой со значением «да / нет», чтобы определить, входит ли плата в топ-80 или нет.

Я попробовал следующий код, который не работает, и я получаю сообщение об ошибке

В списке выбора может быть указано только одно выражение, если подзапрос не введен с помощью EXISTS

Я программист-самоучка, поэтому, вероятно, упускаю что-то очевидное!

Большое спасибо за ваш совет по этому поводу.

Стюарт

 select 
    hCODE as 'Fee Code',
    case 
       when hCODE in (select top 80 hCODE, sum(hPRICE) 
                      from dbo.History
                      where hDONE >= dateadd(year,-1,getdate())
                      group by hCODE
                      order by sum(hPRICE) desc) 
          then 'Top 80' 
          else 'Other' 
    end as 'In Top 80'
from 
    dbo.History;
 

Комментарии:

1. SQL Server. Спасибо.

Ответ №1:

Проблема в этом коде в when условии:

 when hCODE in (select top 80 hCODE, sum(hPRICE) 
               .....
 

Ваш select возвращает два столбца для каждой строки результирующего набора — но вы проверяете, есть ли в этом наборе одно значение ( hCODE ). Здесь вы не можете вернуть два значения из подзапроса — только то, с которым hCODE сравнивается ваше значение.

Ответ №2:

Решение с нумерацией строк и оконным управлением будет намного более эффективным, чем ваш существующий подзапрос:

 select 
    hCODE as [Fee Code],
    case 
       when ROW_NUMBER() OVER (ORDER BY TotalPerCode DESC) <= 80
          then 'Top 80' 
          else 'Other' 
    end as [In Top 80]
from 
    (SELECT *, SUM(hPRICE) OVER (PARTITION BY hCODE) AS TotalPerCode
    FROM dbo.History
    where hDONE >= dateadd(year,-1,getdate())
) h;
 

Вы также можете сделать это с помощью a GROUP BY , поскольку вам нужно только hCODE значение:

 select 
    hCODE as [Fee Code],
    case 
       when ROW_NUMBER() OVER (ORDER BY TotalPerCode DESC) <= 80
          then 'Top 80' 
          else 'Other' 
    end as [In Top 80]
from 
    (SELECT hCODE, SUM(hPRICE) AS TotalPerCode
    FROM dbo.History
    where hDONE >= dateadd(year,-1,getdate())
    GROUP BY hCODE
) h;
 

Вы должны использовать [] для кавычек имена столбцов с пробелами, а не ''