4

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

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

我的问题是,要获取最新创建的 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 条记录。

4

2 回答 2

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子句的 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')
于 2013-04-02T08:01:25.537 回答
0

在 SQLServer2008 中,您可以将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上的演示

于 2013-04-02T10:17:10.660 回答