SQL 服务器 PARTITION BY 带日期计算
SQL Server PARTITION BY with date calcuation
我正在尝试 运行 一些 SQL 需要 PARTITION BY 但无法解决所需的复杂性。下面的数据被简化了,但想法是使用 table 的前三列来查找第 4 列(我手动添加了值),同时还显示了 table 中的其他列。
对于table中的每个客户,需要统计该客户最后一次询价在当前记录询价日期之前的天数只要在之前小于28天,否则显示NULL。还需要允许可以通过较小的查询列值打破的关系 - 较小的值被计为第一个。
Customer Enquiry EnquiryDate DaysSinceLastEnquiryForCustomer
522181 232853 19/01/2014 NULL
522181 234750 30/01/2014 11
522181 235141 03/02/2014 4
522181 235210 03/02/2014 4
522181 262015 23/09/2014 NULL
522181 263942 09/10/2014 16
522181 265583 22/10/2014 13
522181 311345 01/10/2015 NULL
522181 321938 31/12/2015 NULL
522181 322404 31/12/2015 0
522181 328057 27/01/2016 23
522181 329164 02/02/2016 6
522181 329426 03/02/2016 1
522181 336409 17/03/2016 14
522181 336581 18/03/2016 1
522181 337003 22/03/2016 4
522181 343338 15/05/2016 NULL
522181 344185 23/05/2016 8
522181 352323 06/08/2016 14
提前致谢
不确定我是否理解该逻辑如何产生这些结果。但这里有一个示例可以玩:
注意在 SSMS(或 VS)中,如果您按住 Shift+Alt 和箭头 up/down,您会得到一个 "vertical selection",您可以在其中在多列中键入相同的值。如此轻松地将上述固定宽度 table 转换为 INSERT .. VALUES 查询。
use tempdb
go
drop table if exists C
create table C(Customer int, Enquiry int, EnquiryDate date)
insert into C(Customer,Enquiry,EnquiryDate)
values
--Customer Enquiry EnquiryDate DaysSinceLastEnquiryForCustomer
(522181, 232853,parse('19/01/2014' as date using 'en-GB')),-- NULL
(522181, 234750,parse('30/01/2014' as date using 'en-GB')),-- 11
(522181, 235141,parse('03/02/2014' as date using 'en-GB')),-- 5
(522181, 235210,parse('03/02/2014' as date using 'en-GB')),-- 5
(522181, 262015,parse('23/09/2014' as date using 'en-GB')),-- NULL
(522181, 263942,parse('09/10/2014' as date using 'en-GB')),-- NULL
(522181, 265583,parse('22/10/2014' as date using 'en-GB')),-- 13
(522181, 311345,parse('01/10/2015' as date using 'en-GB')),-- 10
(522181, 321938,parse('31/12/2015' as date using 'en-GB')),-- NULL
(522181, 322404,parse('31/12/2015' as date using 'en-GB')),-- 0
(522181, 328057,parse('27/01/2016' as date using 'en-GB')),-- 23
(522181, 329164,parse('02/02/2016' as date using 'en-GB')),-- 6
(522181, 329426,parse('03/02/2016' as date using 'en-GB')),-- 1
(522181, 336409,parse('17/03/2016' as date using 'en-GB')),-- 14
(522181, 336581,parse('18/03/2016' as date using 'en-GB')),-- 1
(522181, 337003,parse('22/03/2016' as date using 'en-GB')),-- 4
(522181, 343338,parse('15/05/2016' as date using 'en-GB')),-- NULL
(522181, 344185,parse('23/05/2016' as date using 'en-GB')),-- 8
(522181, 352323,parse('06/08/2016' as date using 'en-GB'))-- 14
select *, prev.daysSince
from C c1
outer apply
(
select top 1 *, datediff(day, c2.EnquiryDate, c1.EnquiryDate) daysSince
from C c2
where c2.Customer = c1.Customer
and c2.Enquiry != c1.Enquiry
and c2.EnquiryDate < c1.EnquiryDate
and datediff(day, c2.EnquiryDate, c1.EnquiryDate) < 28
order by c2.EnquiryDate desc
) prev
order by c1.Customer,c1.Enquiry
我正在尝试 运行 一些 SQL 需要 PARTITION BY 但无法解决所需的复杂性。下面的数据被简化了,但想法是使用 table 的前三列来查找第 4 列(我手动添加了值),同时还显示了 table 中的其他列。
对于table中的每个客户,需要统计该客户最后一次询价在当前记录询价日期之前的天数只要在之前小于28天,否则显示NULL。还需要允许可以通过较小的查询列值打破的关系 - 较小的值被计为第一个。
Customer Enquiry EnquiryDate DaysSinceLastEnquiryForCustomer
522181 232853 19/01/2014 NULL
522181 234750 30/01/2014 11
522181 235141 03/02/2014 4
522181 235210 03/02/2014 4
522181 262015 23/09/2014 NULL
522181 263942 09/10/2014 16
522181 265583 22/10/2014 13
522181 311345 01/10/2015 NULL
522181 321938 31/12/2015 NULL
522181 322404 31/12/2015 0
522181 328057 27/01/2016 23
522181 329164 02/02/2016 6
522181 329426 03/02/2016 1
522181 336409 17/03/2016 14
522181 336581 18/03/2016 1
522181 337003 22/03/2016 4
522181 343338 15/05/2016 NULL
522181 344185 23/05/2016 8
522181 352323 06/08/2016 14
提前致谢
不确定我是否理解该逻辑如何产生这些结果。但这里有一个示例可以玩:
注意在 SSMS(或 VS)中,如果您按住 Shift+Alt 和箭头 up/down,您会得到一个 "vertical selection",您可以在其中在多列中键入相同的值。如此轻松地将上述固定宽度 table 转换为 INSERT .. VALUES 查询。
use tempdb
go
drop table if exists C
create table C(Customer int, Enquiry int, EnquiryDate date)
insert into C(Customer,Enquiry,EnquiryDate)
values
--Customer Enquiry EnquiryDate DaysSinceLastEnquiryForCustomer
(522181, 232853,parse('19/01/2014' as date using 'en-GB')),-- NULL
(522181, 234750,parse('30/01/2014' as date using 'en-GB')),-- 11
(522181, 235141,parse('03/02/2014' as date using 'en-GB')),-- 5
(522181, 235210,parse('03/02/2014' as date using 'en-GB')),-- 5
(522181, 262015,parse('23/09/2014' as date using 'en-GB')),-- NULL
(522181, 263942,parse('09/10/2014' as date using 'en-GB')),-- NULL
(522181, 265583,parse('22/10/2014' as date using 'en-GB')),-- 13
(522181, 311345,parse('01/10/2015' as date using 'en-GB')),-- 10
(522181, 321938,parse('31/12/2015' as date using 'en-GB')),-- NULL
(522181, 322404,parse('31/12/2015' as date using 'en-GB')),-- 0
(522181, 328057,parse('27/01/2016' as date using 'en-GB')),-- 23
(522181, 329164,parse('02/02/2016' as date using 'en-GB')),-- 6
(522181, 329426,parse('03/02/2016' as date using 'en-GB')),-- 1
(522181, 336409,parse('17/03/2016' as date using 'en-GB')),-- 14
(522181, 336581,parse('18/03/2016' as date using 'en-GB')),-- 1
(522181, 337003,parse('22/03/2016' as date using 'en-GB')),-- 4
(522181, 343338,parse('15/05/2016' as date using 'en-GB')),-- NULL
(522181, 344185,parse('23/05/2016' as date using 'en-GB')),-- 8
(522181, 352323,parse('06/08/2016' as date using 'en-GB'))-- 14
select *, prev.daysSince
from C c1
outer apply
(
select top 1 *, datediff(day, c2.EnquiryDate, c1.EnquiryDate) daysSince
from C c2
where c2.Customer = c1.Customer
and c2.Enquiry != c1.Enquiry
and c2.EnquiryDate < c1.EnquiryDate
and datediff(day, c2.EnquiryDate, c1.EnquiryDate) < 28
order by c2.EnquiryDate desc
) prev
order by c1.Customer,c1.Enquiry