2013-12-24 7 views
0

У меня есть таблица sales с колоннамиКак показать один столбец в два столбца базы на второй столбец в SQL Server

Month SalesAmount 
-------------------------- 
4 50000 
5 60000 
6 70000 
7 50000 
8 60000 
9 40000 

Я хочу привести как этот

From Month To Month Result 
----------------------------------------------- 
4     6 Increasing 
6     7 Decreasing 
7     8 Increasing 
8     9 Decreasing 

без использования курсора

+4

** Что ** есть ** ВЫ ** пробовали? –

+0

Какую версию SQL Server вы используете? – GarethD

ответ

2

Попробуйте это. В принципе, вам нужно присоединить таблицу к себе месяцем (+1), а затем потянуть нужные данные/выполнить любые вычисления.

Select 
    M1.Month as [From], 
    M2.Month as [To], 
    Case 
     When M2.SalesAmount > M1.SalesAmount Then 'Increasing' 
     When M2.SalesAmount < M1.SalesAmount Then 'Decreasing' 
     Else 'Holding Steady' 
    End 
From sales M1 
    Inner Join sales M2 on M2.Month = M1.Month + 1 

Это работает, если вы хотите провести разбивку по месяцам. Однако ваш примерный набор данных сжимает месяцы 4-6. Без дополнительной информации о том, как вы определяете, что нужно сжать, я сделаю следующие предположения:

  • Вы хотите получить подробные данные за последние 3 периода и сжатую сводку всех остальных периодов.
  • Вы хотите только общий тренд между первым месяцем и последним месяцем в сжатом периоде. т. е. вы хотите узнать разницу между значениями первого и последнего месяца.

Для этого запрос начинает усложняться. Я сделал это с двумя Unioned запросов:

With 
compressed_range as 
(select min([Month]) as min_month, max([Month]) - 3 as max_month from sales) 
Select 
    M1.[Month] as [From], 
    M2.[Month] as [To], 
    Case 
     When M2.SalesAmount > M1.SalesAmount Then 'Increasing' 
     When M2.SalesAmount < M1.SalesAmount Then 'Decreasing' 
     Else 'Holding Steady' 
    End 
From sales M1 
    Inner Join sales M2 on M2.[Month] = (select max_month from compressed_range) 
Where M1.Month = (select min_month from compressed_range) 
Union All 
Select 
    M1.Month as [From], 
    M2.Month as [To], 
    Case 
     When M2.SalesAmount > M1.SalesAmount Then 'Increasing' 
     When M2.SalesAmount < M1.SalesAmount Then 'Decreasing' 
     Else 'Holding Steady' 
    End 
From sales M1 
    Inner Join sales M2 on M2.Month = M1.Month + 1 
Where M2.Month >= (Select max_month + 1 from compressed_range) 
+0

Будет ли это решать вопрос с 'включенными 'значениями? Обратите внимание на данные образца, предоставленные OP - запись «5 60000» включена в первый период в новой таблице. – gotqn

+0

Справедливая точка, я пропустил эту часть. Мне нужно больше информации о том, как вы идентифицируете 4-6, следует сгруппировать в этом сценарии. В противном случае это просто произвольное задание. Я предполагаю (на данный момент) и придумаю обновление. –

+0

Я думаю, что вы, возможно, пропустили этот пункт, 4 - 6 сгруппированы вместе, потому что это непрерывный период увеличения, поэтому, если месяц 7 имел объем продаж 80000 (т.е. увеличение с 6-го месяца), тогда 4-7 сгруппированы вместе. – GarethD

0

Это дает желаемый результат:

DECLARE @T TABLE (Month INT, SalesAmount MONEY); 
INSERT @T 
VALUES (4, 50000), (5, 60000), (6, 70000), (7, 50000), (8, 60000), (9, 40000); 

WITH CTE AS 
( SELECT FromMonth = T2.Month, 
      ToMonth = T.Month, 
      Result = CASE T2.Result 
         WHEN -1 THEN 'Decreasing' 
         WHEN 0 THEN 'Static' 
         WHEN 1 THEN 'Increasing' 
        END, 
      GroupingSet = ROW_NUMBER() OVER(ORDER BY T.Month) - ROW_NUMBER() OVER(PARTITION BY T2.Result ORDER BY T.Month) 
    FROM @T T 
      CROSS APPLY 
      ( SELECT TOP 1 
         T2.SalesAmount, 
         T2.Month, 
         Result = SIGN(T.SalesAmount - T2.SalesAmount) 
       FROM @T T2 
       WHERE T2.Month < T.Month 
       ORDER BY T2.Month DESC 
      ) T2 
) 
SELECT FromMonth = MIN(FromMonth), 
     ToMonth = MAX(ToMonth), 
     Result 
FROM CTE 
GROUP BY Result, GroupingSet 
ORDER BY FromMonth; 

Первый этап должен получить объем продаж за предыдущий месяц каждый раз:

SELECT * 
FROM @T T 
     CROSS APPLY 
     ( SELECT TOP 1 
        T2.SalesAmount, 
        T2.Month, 
        Result = SIGN(T.SalesAmount - T2.SalesAmount) 
      FROM @T T2 
      WHERE T2.Month < T.Month 
      ORDER BY T2.Month DESC 
     ) T2 
ORDER BY T.MONTH 

Даст:

Month SalesAmount SalesAmount Month Result 
5  60000.00 50000.00 4  1.00 
6  70000.00 60000.00 5  1.00 
7  50000.00 70000.00 6  -1.00 
8  60000.00 50000.00 7  1.00 
9  40000.00 60000.00 8  -1.00 

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

RN1 = ROW_NUMBER() OVER(ORDER BY T.Month), 
RN2 = ROW_NUMBER() OVER(PARTITION BY T2.Result ORDER BY T.Month) 

Month SalesAmount SalesAmount Month Result RN1 RN2 | RN1 - RN2 
5  60000.00 50000.00 4  1.00 1 1 |  0 
6  70000.00 60000.00 5  1.00 2 2 |  0 
7  50000.00 70000.00 6  -1.00 3 1 |  2 
8  60000.00 50000.00 7  1.00 4 3 |  1 
9  40000.00 60000.00 8  -1.00 5 2 |  3 

Таким образом, вы можете увидеть в течение первых 2-х строк в последней колонке RN1 - RN2 остается таким же, как они оба увеличиваются, тогда, когда результат изменяется, разница между этими двумя row_numbers chnages, поэтому создает новую группу.

Затем вы можете группировать этот расчет (столбец GroupingSet в исходном запросе), чтобы группировать ваши последовательные периоды увеличения и уменьшения вместе.

Example on SQL Fiddle

0

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

SELECT s1.month AS From_Month, 
     s2.month AS To_Month, 
     CASE 
     WHEN s2.salesamount > s1.salesamount THEN 'Increasing' 
     ELSE 'Decresing' 
     END  AS res 
FROM sales AS s1, 
     sales AS s2 
WHERE s1.month + 1 = s2.month 

демо на http://sqlfiddle.com/#!6/0819d/11

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