SQL группировать по данным с отдельной строкой

sql sql-server

54 просмотра

2 ответа

Я хотел бы сгруппировать по Customer & Date и сгенерировать столбцы count для 2 отдельных значений (Flag = Y и Flag = N). Таблица ввода выглядит следующим образом:

Customer  Date   Flag
------- ------- -----
001      201201  Y
001      201202  Y
001      201203  Y
001      201204  N
001      201205  N
001      201206  Y
001      201207  Y
001      201208  Y
001      201209  N
002         201201  N
002         201202  Y
002         201203  Y
002         201205  N

Вывод должен выглядеть так:

Customer MinDate  MaxDate Count_Y
------- ------ ------- -------
001     201201  201203     3  
001     201206  201208     3     
002     201202  201203     2     

Как я могу написать запрос SQL? Любая помощь приветствуется! Спасибо!

Автор: Cappu Источник Размещён: 08.11.2019 10:57

Ответы (2)


1 плюс

Решение

Вы хотите найти последовательные значения «Y». Это проблема "пробелов и островов", и существует два основных подхода:

  • Определите первое «Y» в каждой группе и используйте эту информацию для определения группы последовательных значений «Y».
  • Используйте разницу row_number()значений для расчета.

Первый зависит от SQL Server 2012+, и вы не указали версию. Итак, вторая выглядит так:

select customer, min(date) as mindate, max(date) as maxdate,
       count(*) as numYs
from (select t.*,
             row_number() over (partition by customer order by date) as seqnum_cd,
             row_number() over (partition by customer, flag order by date) as seqnum_cfd
      from t
     ) t
where flag = 'Y'
group by customer, (seqnum_cd - seqnum_cfd), flag;

Немного сложно объяснить, как это работает. По моему опыту, если вы запустите подзапрос, вы увидите, как вычисляются столбцы seqnum, и «получаете его», наблюдая за результатами.

Примечание. Предполагается, что в день записывается не более одной записи. Если их больше, вы можете использовать dense_rank()вместо того row_number()же эффекта.

Автор: Gordon Linoff Размещён: 20.08.2016 11:25

0 плюса

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

DROP TABLE [GroupCustomer]
GO

CREATE TABLE [dbo].[GroupCustomer](
     Customer VARCHAR(50),
     [Date] [datetime] NULL,
     Flag VARCHAR(1)
       )

INSERT INTO [dbo].[GroupCustomer]  (Customer ,[Date],Flag)
VALUES   ('001','201201','Y'),('001','201202','Y'),
         ('001','201203','Y'),('001','201204','N'),
         ('001','201205','N'),('001','201206','Y'),
         ('001','201207','Y'),('001','201208','Y'),
         ('001','201209','N'),('002','201201','N'),
         ('002','201202','Y'),('002','201203','Y'),
         ('002','201205','N')
GO


;WITH cte_cnt
AS
(
 SELECT Customer,Format(MIN([Date]),'yyMMdd') AS MinDate
   ,Format(MAX([Date]),'yyMMdd') AS MaxDate
   , COUNT('A') AS Count_Y
 FROM (
     SELECT Customer,Flag,[Date],
        ROW_NUMBER() OVER(Partition by customer ORDER BY [Date]) AS ROW_NUMBER,
        DATEDIFF(D, ROW_NUMBER() OVER(Partition by customer ORDER BY [Date])
        , [Date]) AS Diff
    FROM [GroupCustomer]
    WHERE Flag='Y') AS dt
   GROUP BY Customer,Flag, Diff )
SELECT *
FROM  cte_cnt  c
ORDER BY Customer

GO
Автор: Unnikrishnan R Размещён: 20.08.2016 07:31
Вопросы из категории :
32x32