2013-05-31 8 views
2

Мне нужно вернуть 10 лучших продуктов в год, как я могу это сделать с помощью моего следующего запроса?Return top 10 in year

SELECT 
    DP.ProductID 
    , DP.Name 
    , Year(FS.OrderDate) as TheYear 
    , FS.OrderQty 
    , FS.OrderAmount 
FROM dbo.DimProduct AS DP 
LEFT JOIN dbo.FactSales as FS on FS.ProductID = DP.ProductID 
+1

Топ 10 - На основании каких критериев? – sgeddes

+0

См. Предыдущие усилия для аналогичной задачи http://stackoverflow.com/questions/176964/select-top-10-records-for-each-category – xQbert

+0

По количеству проданной продукции – Etienne

ответ

3

Это должно быть легко, если ваша СУБД поддерживает Window Functions

SELECT ProductID, 
     Name, 
     TheYear, 
     OrderQty, 
     OrderAmount 
FROM  
     (
      SELECT DP.ProductID 
        ,DP.Name 
        ,Year(FS.OrderDate) as TheYear 
        ,FS.OrderQty 
        ,FS.OrderAmount, 
        ,ROW_NUMBER() OVER() (PARTITION BY Year(FS.OrderDate) 
             ORDER BY FS.OrderQty DESC) rn 
      FROM dbo.DimProduct AS DP 
        LEFT JOIN dbo.FactSales as FS 
         on FS.ProductID = DP.ProductID 
     ) s 
WHERE rn <= 10 
ORDER BY TheYear 

Текущий запрос даст вам 10 продукты для каждого TheYear на основе FS.OrderQty, так как вы не имеете упомянутые критерии о том, как будут сортироваться записи .

ROW_NUMBER() (функция РАНЖИРОВАНИЕ) будет генерировать последовательность числа для каждой группы, в данном случае Year(FS.OrderDate), что сортируется на основании FS.OrderQty. Затем записи будут отфильтрованы на основе значения сгенерированной последовательности.


Однако, если ROW_NUMBER() не будет генерировать TIE на записи одного и того же FS.OrderQty. Если вы хотите, чтобы с ним обращались, используйте DENSE_RANK() вместо ROW_NUMBER().

+3

Я предполагаю, что продукт ТОП 10 каждого из год означает «OrderQty * OrderAmount». –

+0

Возможно, ищет ORDER BY FS.OrderQty или FS.OrderAmount для 10 лучших продуктов в год. Подумайте о продажах. –

+0

@TimSchmelter хорошая вещь. не уверен, поскольку ОП не упоминал о каких-либо критериях. –

3

Вы хотите использовать функцию row_number(), чтобы получить верхнюю 10. При этом предполагается, что OrderQty определяет топ-10:

select t.* 
from (SELECT DP.ProductID, DP.Name, Year(FS.OrderDate) as TheYear, FS.OrderQty, FS.OrderAmount, 
      row_number() over (partition by Year(FS.OrderDate) 
           order by fs.OrderAmount desc 
           ) as seqnum 
     FROM dbo.DimProduct DP LEFT JOIN 
      dbo.FactSales FS 
      on FS.ProductID = DP.ProductID 
    ) t 
where seqnum <= 10; 

Функция row_number() перебирает строки, начиная с 1. Она начинается над внутри каждой группы, как определено в пункте partition by (в вашем случае, году). Порядок номеров основан на условии order by (в вашем случае fs.OrderAmount desc). Таким образом, десять лучших продуктов в каждом году будут иметь номера 1-10, а предложение where просто выбирает их.

0
SELECT 
    DP.ProductID 
    , DP.Name 
    , Year(FS.OrderDate) as TheYear 
    , FS.OrderQty 
    , FS.OrderAmount 
    , (FS.OrderQty * FS.OrderAmount) AS FS.Total 
FROM dbo.DimProduct AS DP 
LEFT JOIN dbo.FactSales as FS on FS.ProductID = DP.ProductID 
GROUP BY TheYear, DP.ProductID, FS.Total 
ORDER BY FS.Total DESC 
WHERE seqnum <= 10; 
+3

Он хочет десятку продуктов каждый год, а не только один год ... –

+0

Я изменил код, чтобы отображать десятку продуктов каждый год. – Gimmy

+0

, но не ограничивает выход только до 10 значений ... –