查找列值在它们之间相等的顶部连续行

时间:2017-09-21 09:52:38

标签: sql sql-server tsql

我需要获得列值相等的所有连续顶行

我的表是:

CREATE TABLE [dbo].[Items](
  [Id] [int]  NOT NULL,
  [IdUser] [int] NOT NULL,
  [CreatedDate] [datetime] NOT NULL,
  [SomeData] nvarchar(50) NOT NULL);

我希望顶行(按Id desc排序)与IdUser

相同

如果表数据是:

Id  IdUser  CreatedDate                 SomeData
--- ------- ------------------------    --------
1   1       2017-09-21T09:42:01.407Z    sdafsasfa
2   1       2017-09-21T09:42:01.407Z    sdafsasfa
4   2       2017-09-21T09:42:01.41Z     sdafsasfa
5   3       2017-09-21T09:42:01.41Z     sdafsasfa
7   3       2017-09-21T09:42:01.413Z    sdafsasfa
8   3       2017-09-21T09:42:01.413Z    sdafsasfa
9   10      2017-09-21T09:42:01.417Z    sdafsasfa
11  11      2017-09-21T09:42:01.417Z    sdafsasfa
12  2       2017-09-21T09:42:01.42Z     sdafsasfa
15  2       2017-09-21T09:42:01.42Z     sdafsasfa

我想:

Id  IdUser  CreatedDate                 SomeData
--- ------- ------------------------    --------
12  2       2017-09-21T09:42:01.42Z     sdafsasfa
15  2       2017-09-21T09:42:01.42Z     sdafsasfa

如果表数据是:

Id  IdUser  CreatedDate                 SomeData
--- ------- ------------------------    --------
1   1       2017-09-21T09:42:01.407Z    sdafsasfa
2   1       2017-09-21T09:42:01.407Z    sdafsasfa
4   2       2017-09-21T09:42:01.41Z     sdafsasfa

我想:

Id  IdUser  CreatedDate                 SomeData
--- ------- ------------------------    --------
4   2       2017-09-21T09:42:01.41Z     sdafsasfa

SqlFiddle

5 个答案:

答案 0 :(得分:1)

您可以尝试此查询:

select I.* 
from 
[dbo].[Items] I 
JOIN
(select top 1 Id, IdUser from [dbo].[Items] order by Id desc)I2
on I.Iduser=I2.Iduser
order by Id desc;-- this can be removed to remove ordering by Id Desc

updated fiddle link

答案 1 :(得分:1)

假设您想要具有最高CreateDate和相同IdUser的最后一行,那么DENSE_RANK将有助于

SELECT id, iduser, CreatedDate, somedata
FROM (
    SELECT id, iduser, CreatedDate, somedata, 
           DENSE_RANK() OVER (ORDER BY CreatedDate desc, IdUser) ord
    FROM [dbo].[Items]) t
WHERE t.ord = 1

等效的SQL查询是

SELECT *
FROM Items t1
WHERE NOT EXISTS (
         SELECT *
         FROM Items t2
         WHERE t2.createddate > t1.createddate or 
              (t2.createddate = t1.createddate and t2.iduser < t1.iduser)
      )

demo

答案 2 :(得分:1)

您可以像这样使用LAGSUM() OVER()

DECLARE @Items as Table 
(
  [Id] [int]  NOT NULL,
  [IdUser] [int] NOT NULL,
  [CreatedDate] [datetime] NOT NULL,
  [SomeData] nvarchar(50) NOT NULL
);

INSERT INTO @Items
(
    Id,
    IdUser,
    CreatedDate,
    SomeData
)
VALUES

( 1 , 1 ,getdate(),'sdafsasfa'),
( 2 , 1 ,getdate(),'sdafsasfa'),
( 4 , 2 ,getdate(),'sdafsasfa'),
( 5 , 3 ,getdate(),'sdafsasfa'),
( 7 , 3 ,getdate(),'sdafsasfa'),
( 8 , 3 ,getdate(),'sdafsasfa'),
( 9 , 10,getdate(),'sdafsasfa'),
( 11, 11,getdate(),'sdafsasfa'),
( 12, 2 ,getdate(),'sdafsasfa'),
( 15, 2 ,getdate(),'sdafsasfa')

;WITH temp AS 
(
    SELECT *,
         CASE 
            WHEN  lag(i.IdUser) over(ORDER BY i.Id) = i.IdUser THEN 0
            ELSE 1
         END as ChangingPoint          
    FROM @Items i
),
temp1 AS
(
    SELECT 
          *,
          sum(t.ChangingPoint) OVER(ORDER BY t.Id) as GroupId
    FROM temp t
)

SELECT TOP 1 WITH TIES
       t.Id,
       t.IdUser,
       t.CreatedDate,
       t.SomeData
FROM temp1 t
ORDER BY GroupId  DESC

在此处查看演示:http://rextester.com/PHWWU96232

答案 3 :(得分:0)

尽管TriV's solution工作正常但我最终使用了修改后的Radim Bača's solution(他的解决方案不能正常工作),因为IMO速度更快

SELECT id, iduser, createddate, somedata
FROM Items t1
WHERE NOT EXISTS (
         SELECT 1
         FROM Items t2
         WHERE t2.id > t1.id and t2.iduser <> t1.iduser  );

SQLFiddle

答案 4 :(得分:0)

select I.* 
from 
[dbo].[Items1] I 
JOIN
(select top 1 Id, IdUser,CreatedDate from [dbo].[Items1] order by Id desc)I2
on I.CreatedDate=I2.CreatedDate
order by Id desc;-- this can be removed to remove ordering by Id Desc