2013-04-30 2 views
7

Я пытаюсь выяснить, как вернуть 10 лучших записей для каждой группы Trans.TranSID.t-SQL, чтобы найти 10 лучших записей для каждой группы

SELECT a.ABID, a.ABName, t.TranSID, SUM(IIF(TranTypeID = 'CO', td.Qty * CAST(td.Price AS money) * - 1, 
         td.Qty * CAST(td.Price AS money))) AS TotalSales 
FROM   Trans t INNER JOIN 
         TransDetail td ON t.TranID = td.TranID INNER JOIN 
         ABook a ON t.TranABID = a.ABID 
WHERE  (t.TranDate BETWEEN CONVERT(DATETIME, '2012-01-01 00:00:00', 102) AND CONVERT(DATETIME, '2013-01-01 00:00:00', 102)) AND 
      t.TranTypeID in ('SO','CA','CO') AND (t.TranStatus <> 'V') 
GROUP BY a.ABID, a.ABName, t.TranSID 
HAVING (NOT (a.ABName LIKE '%cash%')) 
ORDER BY t.TranSID, TotalSales Desc 

Я могу добавить «TOP 10» в оператор выбора, но это дает мне первые 10 счетов независимо от группы. Есть 25 групп Trans.TranSID, и я пытаюсь получить 10 лучших только для каждой группы.

+0

Включение базовой структуры таблицы и ожидаемого результата поможет получить ответы. – jTC

+0

В основном таблицы таблиц счетов (Abook) и транзакции (Trans) и транзакции (TransDetail). Очень простая структура. Просто хочу суммировать продажи для каждого клиента и группировать 10 лучших результатов для TranSID (который является местом нахождения транзакции). –

ответ

10

Я думаю, что вы ищете ROW_NUMBER() с PARTITION BY

SELECT * 
FROM (
    SELECT 
     ROW_NUMBER() OVER(PARTITION BY t.TranSID ORDER BY t.TranSID, SUM(IIF(TranTypeID = 'CO', td.Qty * CAST(td.Price AS money) * - 1, td.Qty * CAST(td.Price AS money))) DESC) as RowNum,    
     a.ABID, 
     a.ABName, 
     t.TranSID, 
     SUM(IIF(TranTypeID = 'CO', td.Qty * CAST(td.Price AS money) * - 1, td.Qty * CAST(td.Price AS money))) AS TotalSales 
    FROM Trans t 
     INNER JOIN TransDetail td 
      ON t.TranID = td.TranID 
     INNER JOIN ABook a 
      ON t.TranABID = a.ABID 
    WHERE (t.TranDate BETWEEN CONVERT(DATETIME, '2012-01-01 00:00:00', 102) AND CONVERT(DATETIME, '2013-01-01 00:00:00', 102)) 
     AND t.TranTypeID in ('SO','CA','CO') 
     AND (t.TranStatus <> 'V') 
    GROUP BY a.ABID, a.ABName, t.TranSID 
    HAVING (NOT (a.ABName LIKE '%cash%')) 
) a 
WHERE a.RowNum <=10 

это присвоит номер строки для каждой записи в группировке (колонны, определяемой PARTITION, идущей от 1 до п. Оттуда вы можете запустить SELECT на нем, чтобы захватить любое количество записей в группе.

+0

При запуске этого кода появляется следующее сообщение об ошибке. Msg 1033, уровень 15, состояние 1, строка 20 Предложение ORDER BY недопустимо в представлениях, встроенных функциях, производных таблицах, подзапросах и общих табличных выражениях, если также не указаны TOP, OFFSET или FOR XML. –

+0

@GaryGerson, я обновил свой сценарий. Попробуйте удалить «ORDER BY» в нижней части подзапроса – valverij

+0

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

1

Я не очень хорошо знаком с t-sql и, к сожалению, у меня нет доступа к базе данных t-sql для тестирования что это достигает вашей цели.

Это, я думаю, это один из способов, которым вы могли бы выполнить это, используя подзапрос и функцию ROW_NUMBER.

SELECT 
    * 
FROM (
    SELECT 
     a.ABID 
     , a.ABName 
     , t.TranSID 
     , SUM(IFF(TranTypeID = 'CO' 
      , td.Qty * CAST(td.Price AS MONEY) * -1 
      , td.Qty * CAST(td.Price AS MONEY))) AS TotalSales 
     , ROW_NUMBER() 
      OVER(PARTITION BY t.TranSID 
       ORDER BY SUM(IFF(TranTypeID = 'CO' 
        , td.Qty * CAST(td.Price AS MONEY) * -1 
        , td.Qty * CAST(td.Price AS MONEY))) DESC) AS row 
    FROM 
     Trans t 
     INNER JOIN TransDetail td 
     ON t.TranID = td.TranID 

     INNER JOIN ABook a 
     ON t.TranABID = a.ABID 

    WHERE 
     (t.TranDate BETWEEN CONVERT(DATETIME, '2012-01-01 00:00:00', 102) AND CONVERT(DATETIME, '2013-01-01 00:00:00', 102)) 
     AND t.TranTypeID in ('SO','CA','CO') 
     AND (t.TranStatus <> 'V') 

    GROUP BY 
     a.ABID 
     , a.ABName 
     , t.TranSID 

    HAVING 
     (NOT (a.ABName LIKE '%cash%')) 
) q 

WHERE 
    q.row <= 10 
+0

Как и выше, я получаю следующее сообщение об ошибке, когда я запускаю это. Msg 1033, уровень 15, состояние 1, строка 20 Предложение ORDER BY недопустимо в представлениях, встроенных функциях, производных таблицах, подзапросах и общих табличных выражениях, если также не указаны TOP, OFFSET или FOR XML. –

+1

Я считаю, что проблема с вашей первой версией состояла в том, что в поле ROW_NUMBER() было значение «AS TotalSales» внутри функции sum. То, что у вас там сейчас работает. –

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