Sql 查询以获取基于月份的唯一日期
Sql query to get unique date based on month
我正在努力从 table.
中提取一些数据
declare @SampleData as Table(Id int, ContactId int, Item varchar(25),CreatedOn date)
insert into @SampleData
VALUES(100,2500,'Some item name 1212', '9/5/2020'),
(104,2500,'Some item name 2232', '9/15/2020'),
(109,2500,'Some item name 3434', '9/20/2020'),
(112,3000,'Some item name 5422', '8/1/2020'),
(132,3000,'Some item name 344', '9/5/2020'),
(134,3000,'Some item name 454', '9/15/2020'),
(139,3500,'Some item name 6455', '7/5/2020'),
(146,3500,'Some item name 546', '8/5/2020'),
(142,3500,'Some item name 867', '9/5/2020'),
(149,3500,'Some item name 677', '9/15/2020'),
(150,3500,'Some item name 888', '9/19/2020')
这里的逻辑是让你每个月都可以找到新的联系人ID(所以逻辑是如果同一个联系人在从那个月的1号开始的最后28天内没有任何记录,它就被认为是新的联系人)
当您有两个日期期间时,这很容易做到,您可以排除您想要的记录,如下所示
SELECT *
FROM @SampleData
WHERE CreatedOn> = @FromDate
and CreatedOn <=@Date
and ContactId not in (SELECT ContactId
FROM @SampleData
WHERE CreatedOn >= DateAdd(Day, -28,@FromDate)
AND CreatedOn < @FromDate)
我想要的是在没有参数的情况下预填充这些数据 table 以便用户可以使用。
在此示例数据中,我预计 7 月联系 3500,8 月联系 3000,9 月联系 2500&3000。
还需要只显示每个联系人的记录,而不是重复的。
DECLARE @From date,
@To date
DECLARE date_cursor CURSOR FOR
select distinct DATEADD(month, DATEDIFF(month, 0, CreatedOn), 0) FromDate,EOMONTH(CreatedOn) ToDate
from @SampleData
OPEN date_cursor
FETCH NEXT FROM date_cursor INTO @From,@To
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT *
FROM (
SELECT DISTINCT ContactId,@From 'From Date', @To 'To Date'
FROM @SampleData D
WHERE D.CreatedOn>= @From AND D.CreatedOn <= @To
AND ContactId NOT IN (SELECT ContactId
FROM @SampleData
WHERE CreatedOn >= DateAdd(Day, -28,@From)
AND CreatedOn < @From)) ContactData
OUTER APPLY (
--pick first row for the contact as per the period
SELECT TOP 1 *
FROM @SampleData D
WHERE D.ContactId = ContactData.ContactId
AND D.CreatedOn >= ContactData.[From Date]
AND D.CreatedOn < ContactData.[To Date]
ORDER BY CreatedOn
) Records
FETCH NEXT FROM date_cursor INTO @From,@To
END
CLOSE date_cursor
DEALLOCATE date_cursor
结果
ContactId From Date To Date Id Item CreatedOn
3500 01/07/2020 31/07/2020 139 Some item name 6455 05/07/2020
3000 01/08/2020 31/08/2020 112 Some item name 5422 01/08/2020
2500 01/09/2020 30/09/2020 100 Some item name 1212 05/09/2020
3000 01/09/2020 30/09/2020 132 Some item name 344 05/09/2020
我想摆脱光标,有没有可能
您可以使用 lag()
并比较行来为联系人分配一个分组:
select sd.*,
sum(case when prev_createdon > dateadd(day, -28, createdon) then 0 else 1 end) over
(partition by contactid order by createdon) as grouping
from (select sd.*,
lag(createdon) over (partition by contactid order by createdon) as prev_createdon
from SampleData sd
) sd;
如果您只想要一系列相邻记录中的第一行,则:
select sd.*
from (select sd.*,
lag(createdon) over (partition by contactid order by createdon) as prev_createdon
from SampleData sd
) sd
where prev_createdon < dateadd(day, -28, createdon) or prev_createdon is null;
Here 是一个 db<>fiddle.
编辑:
根据修改后的问题,你想分组总结。您可以使用:
select contactid, min(createdon), max(createdon), min(id),
max(case when seqnum = 1 then item end) as item
from (select sd.*,
row_number() over (partition by contactid, grouping order by createdon) as seqnum
from (select sd.*,
sum(case when prev_createdon > dateadd(day, -28, createdon) then 0 else 1 end) over
(partition by contactid order by createdon) as grouping
from (select sd.*,
lag(createdon) over (partition by contactid order by createdon) as prev_createdon
from SampleData sd
) sd
) sd
) sd
group by contactid, grouping;
我更新了数据库 fiddle 也有这个。
我正在努力从 table.
中提取一些数据declare @SampleData as Table(Id int, ContactId int, Item varchar(25),CreatedOn date)
insert into @SampleData
VALUES(100,2500,'Some item name 1212', '9/5/2020'),
(104,2500,'Some item name 2232', '9/15/2020'),
(109,2500,'Some item name 3434', '9/20/2020'),
(112,3000,'Some item name 5422', '8/1/2020'),
(132,3000,'Some item name 344', '9/5/2020'),
(134,3000,'Some item name 454', '9/15/2020'),
(139,3500,'Some item name 6455', '7/5/2020'),
(146,3500,'Some item name 546', '8/5/2020'),
(142,3500,'Some item name 867', '9/5/2020'),
(149,3500,'Some item name 677', '9/15/2020'),
(150,3500,'Some item name 888', '9/19/2020')
这里的逻辑是让你每个月都可以找到新的联系人ID(所以逻辑是如果同一个联系人在从那个月的1号开始的最后28天内没有任何记录,它就被认为是新的联系人)
当您有两个日期期间时,这很容易做到,您可以排除您想要的记录,如下所示
SELECT *
FROM @SampleData
WHERE CreatedOn> = @FromDate
and CreatedOn <=@Date
and ContactId not in (SELECT ContactId
FROM @SampleData
WHERE CreatedOn >= DateAdd(Day, -28,@FromDate)
AND CreatedOn < @FromDate)
我想要的是在没有参数的情况下预填充这些数据 table 以便用户可以使用。
在此示例数据中,我预计 7 月联系 3500,8 月联系 3000,9 月联系 2500&3000。
还需要只显示每个联系人的记录,而不是重复的。
DECLARE @From date,
@To date
DECLARE date_cursor CURSOR FOR
select distinct DATEADD(month, DATEDIFF(month, 0, CreatedOn), 0) FromDate,EOMONTH(CreatedOn) ToDate
from @SampleData
OPEN date_cursor
FETCH NEXT FROM date_cursor INTO @From,@To
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT *
FROM (
SELECT DISTINCT ContactId,@From 'From Date', @To 'To Date'
FROM @SampleData D
WHERE D.CreatedOn>= @From AND D.CreatedOn <= @To
AND ContactId NOT IN (SELECT ContactId
FROM @SampleData
WHERE CreatedOn >= DateAdd(Day, -28,@From)
AND CreatedOn < @From)) ContactData
OUTER APPLY (
--pick first row for the contact as per the period
SELECT TOP 1 *
FROM @SampleData D
WHERE D.ContactId = ContactData.ContactId
AND D.CreatedOn >= ContactData.[From Date]
AND D.CreatedOn < ContactData.[To Date]
ORDER BY CreatedOn
) Records
FETCH NEXT FROM date_cursor INTO @From,@To
END
CLOSE date_cursor
DEALLOCATE date_cursor
结果
ContactId From Date To Date Id Item CreatedOn
3500 01/07/2020 31/07/2020 139 Some item name 6455 05/07/2020
3000 01/08/2020 31/08/2020 112 Some item name 5422 01/08/2020
2500 01/09/2020 30/09/2020 100 Some item name 1212 05/09/2020
3000 01/09/2020 30/09/2020 132 Some item name 344 05/09/2020
我想摆脱光标,有没有可能
您可以使用 lag()
并比较行来为联系人分配一个分组:
select sd.*,
sum(case when prev_createdon > dateadd(day, -28, createdon) then 0 else 1 end) over
(partition by contactid order by createdon) as grouping
from (select sd.*,
lag(createdon) over (partition by contactid order by createdon) as prev_createdon
from SampleData sd
) sd;
如果您只想要一系列相邻记录中的第一行,则:
select sd.*
from (select sd.*,
lag(createdon) over (partition by contactid order by createdon) as prev_createdon
from SampleData sd
) sd
where prev_createdon < dateadd(day, -28, createdon) or prev_createdon is null;
Here 是一个 db<>fiddle.
编辑:
根据修改后的问题,你想分组总结。您可以使用:
select contactid, min(createdon), max(createdon), min(id),
max(case when seqnum = 1 then item end) as item
from (select sd.*,
row_number() over (partition by contactid, grouping order by createdon) as seqnum
from (select sd.*,
sum(case when prev_createdon > dateadd(day, -28, createdon) then 0 else 1 end) over
(partition by contactid order by createdon) as grouping
from (select sd.*,
lag(createdon) over (partition by contactid order by createdon) as prev_createdon
from SampleData sd
) sd
) sd
) sd
group by contactid, grouping;
我更新了数据库 fiddle 也有这个。