2013-04-02 3 views
4

Я использую SQL Server 2008, и мне интересно, могу ли я выполнить свой запрос в одном операторе select и без подзапроса.SQL Select with Group By and Order By Date

Я хочу установить переменную в true, если поле в записи истинно в последних 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 

Просьба предоставить мне ваши предложения.

Вот пример, скажем, мы имеем следующую таблицу, и сказать, что я хочу, чтобы проверить последние 3 записи для каждого ID:

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 

Для ид = «1», то результат будет FALSE поскольку последние 3 созданные записи не имеют значения true для поля JOINED в этих трех записях.

Для id = "2" результат будет TRUE, поскольку последние 3 созданные записи имеют истинное поле JOINED в этих трех записях.

Для id = "3" результат будет FALSE, поскольку последние созданные записи должны быть не менее 3 записей.

+0

вы можете использовать 'IF EXIST' и поместить все ваши условия 'where' – Sachin

+0

Пожалуйста, перечитайте это предложение, я не могу понять: _« где, если поле истинно в последних 10 записях, переменная будет истинна, а если она ложна, переменная будет ложной ».Это поможет, если вы покажете нам образцы данных и желаемый результат. –

+0

Какая версия SQL Server? –

ответ

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 

(Это зависит от SQL Server 2012 версии OVER clause - но вы не указали, какая версия)

Результат:

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') 
+0

WOW мне нужно все, что для моего запроса, не так ли сложно? – user2155873

0

В SQLServer2008 вместо подзапроса вы можете использовать CTE с ROW_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