SQL Server:根据另一个列中值的首次出现创建一个列

时间:2019-12-06 19:03:53

标签: sql sql-server

请考虑SQL Server中的下表:

enter image description here

我想编写一个SQL查询来生成列Indicator。每个类别第一次出现Flag = 1时,此列应设置为1。

例如,对于类别A,日期1/3 / 2019、1 / 4 / 2019、1 / 5 / 2019、1 / 6/2019的Flag列设置为1。由于将Flag设置为1的最早日期是1/3/2019,因此该记录的Indicator列也应设置为1。

我应该为此编写什么SQL Server查询?

PS:该图已经显示了Indicator列所需的输出。

下面是在SQL Server中生成表的代码:

CREATE TABLE myTable
(
    Category CHAR(1),
    Date DATE,
    Flag INT
)

INSERT INTO myTable (Category, Date, Flag) 
VALUES ('A', '2019-01-01', 0), ('A', '2019-02-01', 0),
       ('A', '2019-03-01', 1), ('A', '2019-04-01', 1),
       ('A', '2019-05-01', 1), ('A', '2019-06-01', 1),
       ('B', '2019-01-01', 0), ('B', '2019-02-01', 0),
       ('B', '2019-03-01', 0), ('B', '2019-04-01', 0),
       ('B', '2019-05-01', 1), ('B', '2019-06-01', 1),
       ('C', '2019-01-01', 0), ('C', '2019-02-01', 0),
       ('C', '2019-03-01', 0), ('C', '2019-04-01', 1),
       ('C', '2019-05-01', 1), ('C', '2019-06-01', 1),
       ('C', '2019-07-01', 1)

3 个答案:

答案 0 :(得分:2)

使用派生表和MIN()来找出哪一个是带有标志的类别的第一个日期的一种方法。将其重新连接到原始表。

DEMO

SELECT 
    yt.*
  , ISNULL(b.Indicator, 0) AS Indicator
FROM YourTable yt
LEFT JOIN 
  (SELECT category, MIN(date) AS date, 1 AS Indicator
  FROM dbo.YourTable
  WHERE Flag = 1
  GROUP BY Category) b ON b.Category = yt.Category AND b.date = yt.date

答案 1 :(得分:1)

我正在考虑将min()函数用作窗口函数:

select t.*, 
       (case then t.flag = 1 and
                  t.date = min(t.date) over (partition by t.category, t.flag)
             then 1 else 0
        end) as indicator
from myTable t
order by t.Category, t.date

答案 2 :(得分:0)

另一种方式

DEMO

CREATE TABLE myTable
 (
    Category char(1),
    Date date,
    Flag int
 )

        INSERT INTO myTable (Category, Date, Flag) VALUES
        ('A','2019-01-01',0),
        ('A','2019-02-01',0),
        ('A','2019-03-01',1),
        ('A','2019-04-01',1),
        ('A','2019-05-01',1),
        ('A','2019-06-01',1),
        ('B','2019-01-01',0),
        ('B','2019-02-01',0),
        ('B','2019-03-01',0),
        ('B','2019-04-01',0),
        ('B','2019-05-01',1),
        ('B','2019-06-01',1),
        ('C','2019-01-01',0),
        ('C','2019-02-01',0),
        ('C','2019-03-01',0),
        ('C','2019-04-01',1),
        ('C','2019-05-01',1),
        ('C','2019-06-01',1),
        ('C','2019-07-01',1);

    select t.* , 
    CASE WHEN T.FLAG=1 AND FIRST_VALUE(T.DATE) OVER (PARTITION BY T.Category ORDER BY t.FLAG desc, t.Date asc)=T.DATE THEN 1 
   ELSE 0 END Indicator
    from myTable t
    order by t.Category, t.date