SQL选择分组依据和按日期排序

时间:2013-04-02 07:29:09

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

我正在使用SQL Server 2008,我想知道我是否可以在一个select语句中完成查询而没有子查询。

如果记录中的字段在最后10条创建的记录中为真,我想将变量设置为true,如果该字段在最后10条记录中为真,则该变量为真,而如果该字段为假,则变量将为false,如果记录总数小于10,那么该变量也将为假。

我的问题是,要获取最新的10个创建记录,然后我需要通过降序来进行用户排序并在前10位上执行过滤器,因此我的查询应该如下所示,它不是有效查询:

declare @MyVar bit
set @MyVar = 0

select top(10) @MyVar = 1 from MyTable
where SomeId = 1000 and SomeFlag = 1
group by SomeId
having count(SomeId) >= 10
order by CreatedDate

请告诉我你的建议。

这是一个例子,假设我们有下表,并说我想检查每个id的最新3条记录:

ID  Joined  CreatedDate
1   true    03/27/2013
1   false   03/26/2013
1   false   03/25/2013
1   true    03/24/2013
1   true    03/23/2013

2   true    03/22/2013
2   true    03/21/2013
2   true    03/20/2013
2   false   03/19/2013

3   true    03/18/2013
3   true    03/17/2013

对于id =“1”,结果将为FALSE,因为最近3个创建的记录对于这3条记录中的JOINED字段没有值true。

对于id =“2”,结果将为TRUE,因为最近3条创建的记录在这3条记录中具有真实的JOINED字段。

对于id =“3”,结果将为FALSE,因为要检查的最新创建记录必须至少为3条记录。

2 个答案:

答案 0 :(得分:1)

(在OP指定2008之前给出的答案。以下仅适用于2012年)


此查询给出(对于每个ID值)最后10个标志等于1的行数。应该足够简单(如果需要)将此过滤为仅计数为10的行,并将其限制为单个ID值。

如果没有更好的样本数据,我现在就把它留在那里:

;with Vals as (
    select
        *,
        ROW_NUMBER() OVER (PARTITION BY ID ORDER BY CreatedDate DESC) as rn,
        SUM(CASE WHEN Flag = 1 THEN 1 ELSE 0 END)
                 OVER (PARTITION BY ID
                       ORDER BY CreatedDate ASC
                       ROWS BETWEEN 9 PRECEDING AND CURRENT ROW) as Cnt
    from
        T1
)
select * from Vals where rn = 1

(这取决于OVER clause的SQL Server 2012版本 - 但您没有指定哪个版本)

结果:

ID          Flag  CreatedDate             rn                   Cnt
----------- ----- ----------------------- -------------------- -----------
1           1     2012-01-12 00:00:00.000 1                    10
2           1     2012-01-12 00:00:00.000 1                    9
3           1     2012-01-12 00:00:00.000 1                    6

(只有ID 1符合您的标准)

示例数据:

create table T1 (ID int not null,Flag bit not null,CreatedDate datetime not null)
insert into T1 (ID,Flag,CreatedDate) values
(1,1,'20120101'),
(1,0,'20120102'),
(1,1,'20120103'),
(1,1,'20120104'),
(1,1,'20120105'),
(1,1,'20120106'),
(1,1,'20120107'),
(1,1,'20120108'),
(1,1,'20120109'),
(1,1,'20120110'),
(1,1,'20120111'),
(1,1,'20120112'),

(2,1,'20120101'),
(2,1,'20120102'),
(2,1,'20120103'),
(2,1,'20120104'),
(2,1,'20120105'),
(2,1,'20120106'),
(2,0,'20120107'),
(2,1,'20120108'),
(2,1,'20120109'),
(2,1,'20120110'),
(2,1,'20120111'),
(2,1,'20120112'),

(3,1,'20120107'),
(3,1,'20120108'),
(3,1,'20120109'),
(3,1,'20120110'),
(3,1,'20120111'),
(3,1,'20120112')

答案 1 :(得分:0)

在SQL Server 2008而不是子查询中,您可以将CTEROW_NUMBER()排名函数一起使用

 ;WITH cte AS
 (      
  SELECT ID, CAST(Joined AS int) AS Flag, 
         ROW_NUMBER() OVER(PARTITION BY ID ORDER BY CreatedDate DESC) AS rn
  FROM dbo.test63 t
  )
  SELECT ID, CASE WHEN SUM(Flag) != 3 THEN 0 ELSE 1 END AS Flag
  FROM cte
  WHERE rn <= 3
  GROUP BY ID

SQLFiddle上的演示

相关问题