如何在SQL中设置除last之外的行标志

时间:2018-02-18 10:30:22

标签: sql sql-server sql-server-2008

如何根据除最后一行之外的ROW_NUMBER()设置每一行的标志?

数据表(事件):

+-----+-------------+-----------+----------+----------+
| Ref |   E_Date    |   Item    | Customer | Assignee |
+-----+-------------+-----------+----------+----------+
|   1 | 10/10/2017  | Microsoft | DIB      | Jeffry   |
|   2 | 10/11/2017  | Oracle    | UNB      | Asif     |
|   3 | 10/12/2017  | IBM       | UNB      | John     |
|   4 | 10/13/2017  | Microsoft | DIB      | Asif     |
|   5 | 10//14/2017 | Oracle    | UNB      | Jeffry   |
|   6 | 10/15/2017  | SAP       | DIB      | Said     |
|   7 | 10/15/2017  | Microsoft | DIB      | Said     |
+-----+-------------+-----------+----------+----------+

预期结果:

+-----+------------+-----------+----------+----------+------+
| Ref |   E_Date   |   Item    | Customer | Assignee | Flag |
+-----+------------+-----------+----------+----------+------+
|   1 | 10/10/2017 | Microsoft | DIB      | Jeffry   |    1 |
|   4 | 10/13/2017 | Microsoft | DIB      | Asif     |    1 |
|   7 | 10/15/2017 | Microsoft | DIB      | Said     |    0 |
|   2 | 10/11/2017 | Oracle    | UNB      | Asif     |    1 |
|   5 | 10/14/2017 | Oracle    | UNB      | Jeffry   |    0 |
+-----+------------+-----------+----------+----------+------+

我的查询:

SELECT * FROM
(
    SELECT Ref, E_Date, Item, Customer,Assignee,
    COUNT(*) OVER (PARTITION BY Customer, Item) AS cnt,
    CASE WHEN (ROW_NUMBER() OVER(PARTITION BY Customer, Item ORDER BY Item)) = 1 
    THEN 1   ELSE 0    END Flag
    FROM Events        
) t
WHERE cnt > 1
ORDER BY Item, Customer;

请帮助我获得上述预期结果

的结果

3 个答案:

答案 0 :(得分:3)

查看您的示例,您需要partition by项目(项目更改时重置)和order by参考(根据此确定排名编号)

我不在你的having进入此处,所以把它拿出来

由于您希望根据此顺序识别 last 记录,您只需按降序排序即可。

    SELECT Ref, Date, Item, User,
      CASE WHEN (ROW_NUMBER() 
      OVER(PARTITION BY Item ORDER BY ref DESC)) = 1 
      THEN 1 
      ELSE 0 END Flag,
     COUNT(*) OVER (PARTITION BY User, Item) AS cnt
    FROM Events        
    ORDER BY Item, Ref;

答案 1 :(得分:1)

item列的降序排列userRef列的行号组。然后将行号为1的行设置为1。

<强>查询

;with cte as (
    select [rn] = row_number() over(
        partition by [item], [user]
        order by [ref] desc
    ), *
    from [your_table_name]
)
select [item], [Ref], [Date], [User],
case [rn] when 1 then 0 else 1 end as [Flag]
from cte
order by [Ref];

答案 2 :(得分:0)

我的建议使用可更新的CTE 来获取您想要更改的所有行。诀窍是TOP 1 WITH TIES。我直接在ROW_NUMBER中使用ORDER BY。所有分区的行号将在所需的行中获得1。所有这些都在一起! - TOP 1(由于WITH TIES)。

首先我设置所有标志= 1 ,然后将最后一行(由ref定义)设置为零。

DECLARE @mockupTable TABLE(item VARCHAR(100),Ref INT, [Date] DATE, [User] VARCHAR(100), Flag BIT);
INSERT INTO @mockupTable VALUES
 ('Microsoft',101,'2/11/2018','Jeffrey',1)
,('Microsoft',102,'2/14/2018','Joseph',0)
,('IBM',103,'2/11/2018','Arif',1)
,('IBM',104,'2/15/2018','Arif',1)
,('IBM',105,'2/11/2018','Arif',0)
,('Oracle',106,'2/13/2018','Jeffrey',1)
,('Oracle',107,'2/16/2018','Said',1)
,('Oracle',108,'2/12/2018','Joseph',1)
,('Oracle',109,'2/11/2018','Jeffrey',0);

UPDATE @mockupTable SET Flag=1;

WITH UpdatableCTE AS
(SELECT TOP 1 WITH TIES Flag
 FROM @mockupTable 
 ORDER BY ROW_NUMBER() OVER(PARTITION BY [item] /*,[User] ???*/ ORDER BY [ref] DESC)
)
UPDATE UpdatableCTE SET Flag=0;

- 至少结果与您上面发布的结果相同

SELECT * FROM @mockupTable;