Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Как выбрать все в интервале  [new]
boobonick
Member [заблокирован]

Откуда:
Сообщений: 206
Подскажите, как выбрать все начиная от 4 до 2, отбросив все до и после. При этом 4 и 2 не являются какбэ константами
..............date...........................cnt
2013-03-31 00:00:00.000 0
2013-04-01 00:00:00.000 4
2013-04-02 00:00:00.000 1
2013-04-03 00:00:00.000 0
2013-04-04 00:00:00.000 0
2013-04-05 00:00:00.000 2
2013-04-06 00:00:00.000 0
2013-04-07 00:00:00.000 0
24 июл 13, 21:58    [14613490]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
boobonick
Member [заблокирован]

Откуда:
Сообщений: 206
..............date...........................cnt
2013-03-31 00:00:00.000        0
2013-04-01 00:00:00.000        4
2013-04-02 00:00:00.000        1
2013-04-03 00:00:00.000        0
2013-04-04 00:00:00.000        0
2013-04-05 00:00:00.000        2
2013-04-06 00:00:00.000        0
2013-04-07 00:00:00.000        0 
24 июл 13, 21:59    [14613493]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
boobonick
Member [заблокирован]

Откуда:
Сообщений: 206
т.е., как я понимаю надо выбрать min(date), где cnt>0
и max(date), где cnt>0 и потом betweenом, но как реализовать?
24 июл 13, 22:19    [14613556]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
vewrvwerv
Guest
boobonick,

через зад

;with t(dt, cnt) as
(
	select cast('20130331 00:00:00.000' as datetime), 0 union all
	select '20130401 00:00:00.000', 4 union all
	select '20130402 00:00:00.000', 1 union all
	select '20130403 00:00:00.000', 0 union all
	select '20130404 00:00:00.000', 0 union all
	select '20130405 00:00:00.000', 2 union all
	select '20130406 00:00:00.000', 0 union all
	select '20130407 00:00:00.000', 0
)
select *
from
(
	select *,
		sum(cnt) over(order by dt rows between unbounded preceding and current row) frvd,
		sum(cnt) over(order by dt desc rows between unbounded preceding and current row) bckvd
	from t
) z
where frvd > 0 and bckvd > 0
order by dt desc
24 июл 13, 23:02    [14613743]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
wewefwef
Guest
;with t(dt, cnt) as
(
	select cast('20130331 00:00:00.000' as datetime), 0 union all
	select '20130401 00:00:00.000', 4 union all
	select '20130402 00:00:00.000', 1 union all
	select '20130403 00:00:00.000', 0 union all
	select '20130404 00:00:00.000', 0 union all
	select '20130405 00:00:00.000', 2 union all
	select '20130406 00:00:00.000', 0 union all
	select '20130407 00:00:00.000', 0
)
select t.*
from t
		cross join
(
	select min(dt) min_dt, max(dt) max_dt
	from t
	where cnt > 0
) d
where d.min_dt <= t.dt and t.dt <= d.max_dt
order by t.dt


или так
24 июл 13, 23:07    [14613765]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
boobonick
Member [заблокирован]

Откуда:
Сообщений: 206
Спасибо тебе!
25 июл 13, 00:11    [14613976]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
Добрый Э - Эх
Guest
vewrvwerv
boobonick,

через зад

...
		sum(cnt) over(order by dt rows between unbounded preceding and current row) frvd,
		sum(cnt) over(order by dt desc rows between unbounded preceding and current row) bckvd
...
Можно немного упростить жизнь серверу, сделав в окнах одинаково направленную сортировку (asc, например), просто в одном случае брать preceding-окно, а в другом - following-окно. ;)
25 июл 13, 04:11    [14614188]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
Добрый Э - Эх
Guest
Добрый Э - Эх,

ну как-то так:
;with t(dt, cnt) as
(
	select cast('20130331 00:00:00.000' as datetime), 0 union all
	select '20130401 00:00:00.000', 4 union all
	select '20130402 00:00:00.000', 1 union all
	select '20130403 00:00:00.000', 0 union all
	select '20130404 00:00:00.000', 0 union all
	select '20130405 00:00:00.000', 2 union all
	select '20130406 00:00:00.000', 0 union all
	select '20130407 00:00:00.000', 0
)
select *
from
(
	select *,
		sum(cnt) over(order by dt rows between unbounded preceding and current row) frvd,
		sum(cnt) over(order by dt rows between current row and unbounded following) bckvd
	from t
) z
where frvd > 0 and bckvd > 0
order by dt desc
25 июл 13, 04:16    [14614189]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
можно еще более упростить жизнь серверу, сделав так, как первоначально и предлагалось автором :)
select t.* 
from (
   select min(dt)dtn, max(dt)dtx 
   from t
   where cnt>0
   )g
join t on t.dt between g.dtn and g.dtx
25 июл 13, 05:34    [14614202]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
Добрый Э - Эх
Guest
Cygapb-007,

ну, чуть более кривая реализация этого варианта решения также уже предлагалась...
25 июл 13, 05:47    [14614207]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
Добрый Э - Эх,
да, сходу не заметил, сорь...
только зачем там cross join - я не понял...
хотя сервер все поправил))
25 июл 13, 05:59    [14614211]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
wsrgwergwe
Guest
Добрый Э - Эх
Добрый Э - Эх,

ну как-то так:
;with t(dt, cnt) as
(
	select cast('20130331 00:00:00.000' as datetime), 0 union all
	select '20130401 00:00:00.000', 4 union all
	select '20130402 00:00:00.000', 1 union all
	select '20130403 00:00:00.000', 0 union all
	select '20130404 00:00:00.000', 0 union all
	select '20130405 00:00:00.000', 2 union all
	select '20130406 00:00:00.000', 0 union all
	select '20130407 00:00:00.000', 0
)
select *
from
(
	select *,
		sum(cnt) over(order by dt rows between unbounded preceding and current row) frvd,
		sum(cnt) over(order by dt rows between current row and unbounded following) bckvd
	from t
) z
where frvd > 0 and bckvd > 0
order by dt desc


Планы одинаковые. Сервер делает сортировку в обратном порядке в обоих случаях. Но почему-то с явным desc выходит на 2 секунды быстрее чем following. Вот:

+ тест

create table #t1(dt datetime, cnt int);

;with
l0(n) as (select 1 union all select 1),
l1(n) as (select 1 from l0 t1, l0 t2),
l2(n) as (select 1 from l1 t1, l1 t2),
l3(n) as (select 1 from l2 t1, l2 t2),
l4(n) as (select 1 from l3 t1, l3 t2),
l5(n) as (select 1 from l4 t1, l4 t2),
rt(n) as (select row_number() over(order by (select 0)) from l5 t1, l5 t2)
insert into #t1(dt, cnt)
select top 3000000 dateadd(s, n, '19990101') as dt, cast(rand(checksum(newid())) * 10 as int) as cnt
from rt

create index #idx_t1_zzz on #t1(dt) include(cnt);

set statistics io on;
set statistics time on;

print 'FOLLOWING'

select *
from
(
select *,
sum(cnt) over(order by dt rows between unbounded preceding and current row) frvd,
sum(cnt) over(order by dt rows between current row and unbounded following) bckvd
from #t1
) z
where frvd > 0 and bckvd > 0
order by dt desc

print 'DESC'

select *
from
(
select *,
sum(cnt) over(order by dt rows between unbounded preceding and current row) frvd,
sum(cnt) over(order by dt desc rows between unbounded preceding and current row) bckvd
from #t1
) z
where frvd > 0 and bckvd > 0
order by dt desc

print 'JOIN'

select t.*
from #t1 as t
cross join
(
select min(dt) min_dt, max(dt) max_dt
from #t1
where cnt > 0
) d
where d.min_dt <= t.dt and t.dt <= d.max_dt
order by t.dt

set statistics io off;
set statistics time off;



+ результат

Время синтаксического анализа и компиляции SQL Server:
время ЦП = 0 мс, истекшее время = 0 мс.

Время работы SQL Server:
Время ЦП = 0 мс, затраченное время = 0 мс.
Время синтаксического анализа и компиляции SQL Server:
время ЦП = 11 мс, истекшее время = 11 мс.

Время работы SQL Server:
Время ЦП = 0 мс, затраченное время = 0 мс.

Время работы SQL Server:
Время ЦП = 0 мс, затраченное время = 0 мс.
FOLLOWING

Время работы SQL Server:
Время ЦП = 0 мс, затраченное время = 0 мс.

(3000000 row(s) affected)
Таблица "Worktable". Число просмотров 0, логических чтений 0, физических чтений 0, упреждающих чтений 0, lob логических чтений 0, lob физических чтений 0, lob упреждающих чтений 0.
Таблица "#t1_________________________________________________________________________________________________________________000000000003". Число просмотров 1, логических чтений 9683, физических чтений 0, упреждающих чтений 0, lob логических чтений 0, lob физических чтений 0, lob упреждающих чтений 0.

(1 row(s) affected)

Время работы SQL Server:
Время ЦП = 28733 мс, затраченное время = 47022 мс.
DESC

Время работы SQL Server:
Время ЦП = 0 мс, затраченное время = 0 мс.

(3000000 row(s) affected)
Таблица "Worktable". Число просмотров 0, логических чтений 0, физических чтений 0, упреждающих чтений 0, lob логических чтений 0, lob физических чтений 0, lob упреждающих чтений 0.
Таблица "#t1_________________________________________________________________________________________________________________000000000003". Число просмотров 1, логических чтений 9683, физических чтений 0, упреждающих чтений 0, lob логических чтений 0, lob физических чтений 0, lob упреждающих чтений 0.

(1 row(s) affected)

Время работы SQL Server:
Время ЦП = 29703 мс, затраченное время = 45006 мс.

JOIN

Время работы SQL Server:
Время ЦП = 0 мс, затраченное время = 0 мс.

(3000000 row(s) affected)
Таблица "#t1_________________________________________________________________________________________________________________000000000003". Число просмотров 3, логических чтений 9689, физических чтений 0, упреждающих чтений 0, lob логических чтений 0, lob физических чтений 0, lob упреждающих чтений 0.

(1 row(s) affected)

Время работы SQL Server:
Время ЦП = 1841 мс, затраченное время = 30047 мс.

Время работы SQL Server:
Время ЦП = 0 мс, затраченное время = 0 мс.

25 июл 13, 13:11    [14615830]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать все в интервале  [new]
qwecqew
Guest
че-то недоформатировал тест

+ тест

create table #t1(dt datetime, cnt int);

;with
l0(n) as (select 1 union all select 1),
l1(n) as (select 1 from l0 t1, l0 t2),
l2(n) as (select 1 from l1 t1, l1 t2),
l3(n) as (select 1 from l2 t1, l2 t2),
l4(n) as (select 1 from l3 t1, l3 t2),
l5(n) as (select 1 from l4 t1, l4 t2),
rt(n) as (select row_number() over(order by (select 0)) from l5 t1, l5 t2)
insert into #t1(dt, cnt)
select top 3000000 dateadd(s, n, '19990101') as dt, cast(rand(checksum(newid())) * 10 as int) as cnt
from rt

create index #idx_t1_zzz on #t1(dt) include(cnt);

set statistics io on;
set statistics time on;

print 'FOLLOWING'

select *
from
(
	select *,
		sum(cnt) over(order by dt rows between unbounded preceding and current row) frvd,
		sum(cnt) over(order by dt rows between current row and unbounded following) bckvd
	from #t1
) z
where frvd > 0 and bckvd > 0
order by dt desc

print 'DESC'

select *
from
(
	select *,
		sum(cnt) over(order by dt rows between unbounded preceding and current row) frvd,
		sum(cnt) over(order by dt desc rows between unbounded preceding and current row) bckvd
	from #t1
) z
where frvd > 0 and bckvd > 0
order by dt desc

print 'JOIN'

select t.*
from #t1 as t
		cross join
(
	select min(dt) min_dt, max(dt) max_dt
	from #t1
	where cnt > 0
) d
where d.min_dt <= t.dt and t.dt <= d.max_dt
order by t.dt

set statistics io off;
set statistics time off;

25 июл 13, 13:13    [14615848]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить