Я работаю над извлечением данных из таблицы.
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')
Логика здесь такова, что вы можете найти новый идентификатор контакта каждый месяц (так что логика заключается в том, что если один и тот же контакт не имеет записи за последние 28 дней с 1-го числа этого месяца, он считается новым контактом)
Если у вас есть два периода дат, это легко сделать, поэтому вы можете исключить нужные записи, как показано ниже.
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)
Я хочу предварительно заполнить эти данные без параметров в какой-либо таблице, чтобы пользователь мог их использовать.
В этом примере данных я ожидаю контакта 3500 за июль, 3000 за август и 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
Я бы хотел избавиться от курсора, есть ли возможность
1 ответ
Вы можете назначить группировку контактам, используя 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;
Вот скрипка db <>.
РЕДАКТИРОВАТЬ:
Основываясь на исправленном вопросе, вы хотите подвести итоги по группам. Вы можете сделать это, используя:
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;
Я обновил скрипку БД, чтобы это тоже было.
Похожие вопросы
Новые вопросы
sql
Язык структурированных запросов (SQL) - это язык запросов к базам данных. Вопросы должны включать примеры кода, структуру таблицы, примеры данных и тег для используемой реализации СУБД (например, MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 и т. Д.). Если ваш вопрос относится исключительно к конкретной СУБД (использует определенные расширения / функции), используйте вместо этого тег этой СУБД. Ответы на вопросы, помеченные SQL, должны использовать стандарт ISO / IEC SQL.