У меня очень сложный сценарий, который я пытаюсь реализовать на сервере SQL, чтобы избавить от необходимости вводить много повторяющихся строк данных. Я постараюсь объяснить это в меру своих возможностей. Пожалуйста, прочитайте все внимательно. Несмотря на то, что это довольно длинный пост, я обещаю вам ALL того, что я собираюсь объяснить ниже, в вопросах, касающихся правильного решения этой проблемы.
Каждый день я получаю ежедневный отчет, в котором сообщается обо всех открытых делах. Я создаю ежемесячный подсчет этих событий, который просто добавляет все открытые дела за все эти дни в конец открытого файла дел за эти месяцы. Так что в конце каждого месяца у меня будут данные за 20-22 дня, объединенные для всех выходных и праздничных дней.
Случаи содержат поле с именем [Last_Updated_On], которое является датой его последнего обновления. Есть около 5000 открытых дел каждый день. Однако из этих 5000 примерно 3800 дел каждый день имеют одинаковую дату [Last_Updated_On], что означает, что они являются точными дубликатами всех полей, отображаемых несколько дней подряд, поскольку это ЕДИНСТВЕННОЕ поле, которое когда-либо изменяется, когда дело открыто ,
Как вы можете видеть, если бы я загружал все эти точные дубликаты на сервер, база данных имела бы приблизительно 75 000–80 000 дополнительных записей каждый месяц без какой-либо реальной причины, поскольку подробности дела точно такие же. Поэтому, прежде чем загружать данные каждый месяц, я удаляю дубликаты записей в Excel, оставляя мне только около 20 000 записей с [Case_ID] с уникальной датой [Last_Updated_On].
Допустим, у меня есть следующие столбцы в таблице данных:
[Case_ID], [Last_Updated_On] и [Contact_Date]. Кроме того, я хочу, чтобы было 3 виртуальных вычисляемых столбца - [Дата отчета], [Дата решения] и [Возраст].
Возраст определяется как количество дней, открытых между [Contact_Date] и [Report_Date]. Теперь я хочу передать в Хранимую процедуру две даты: Report_Start_Date и Report_End_Date. [Report_Date] начинается с [Report_Start_Date] и заканчивается [Report_End_Date], увеличиваясь один раз для каждой возвращаемой строки данных. [Resolved_Date] запускает sub_query для проверки таблицы [Resolved_Case] на предмет соответствия [Case_ID], чтобы определить, на какую дату (если она вообще была) разрешен случай.
У меня есть 3 примера того, как это должно работать ниже. Для простоты в этих примерах, скажем, я передаю одну неделю (только M-F) для диапазона дат Report_Date_Start и Report_Date_End (18.03.2009 - 22.03.2009).
В первом случае, допустим, этот случай не разрешен, поэтому он был открыт все 5 дней, и в [Last_Updated_On] изменений не было. Это означает, что он будет хранить только 1 ROW в базе данных, поскольку остальные 4 дня будут точными дубликатами. Однако, когда я возвращаю запрос, мне нужно, чтобы он возвращал 5 ROWS данных, по 1 на каждый день в диапазоне от [Report_Start_Date] до [Report_End_Date]. Единственная разница будет в полях [Age] и [Report_Date], поскольку каждый день, когда дело открывается, возраст увеличивается на 1.
Так что я знаю, что должен быть способ сделать что-то подобное, но я действительно не знаю, с чего начать. Как вернуть несколько строк данных из одной строки? Единственный опыт, который у меня был в этом случае, был, когда я делал Полное соединение, но я не уверен, насколько это применимо к этой ситуации.
Так, например, вот карта из того, что я описал выше:
Data in server:
[Case_ID] [Last_Updated_On] [Contact_Date] [Resolved_Date]
US2309-2323 3/15/2019 3/15/2019 NULL
Query_Returns:
[Case_ID] [Last_Updated_On] [Contact_Date] [Report_Date] [Age]
US2309-2323 3/15/2019 3/15/2019 3/18/2019 1
US2309-2323 3/15/2019 3/15/2019 3/19/2019 2
US2309-2323 3/15/2019 3/15/2019 3/20/2019 3
US2309-2323 3/15/2019 3/15/2019 3/21/2019 4
US2309-2323 3/15/2019 3/15/2019 3/22/2019 5
Как видите, запрос будет возвращать 5 строк - по одной на каждую дату в диапазоне report_date, где report_date меньше resolved_date (или всех дат, если resolved_date имеет значение NULL).
Теперь здесь был бы другой экземпляр с дополнительной строкой для этого случая, основанной на различных датах [Last_Contacted_On], присутствующих там и имеющих несколько строк в базе данных:
Data in server:
[Case_ID] [Last_Updated_On] [Contact_Date] [Resolved_Date]
US2309-2323 3/15/2019 3/15/2019 NULL
US2309-2323 3/19/2019 3/15/2019 NULL
US2309-2323 3/21/2019 3/15/2019 NULL
Query_Returns:
[Case_ID] [Last_Updated_On] [Contact_Date] [Report_Date] [Age]
US2309-2323 3/15/2019 3/15/2019 3/18/2019 1
US2309-2323 3/19/2019 3/15/2019 3/19/2019 2
US2309-2323 3/19/2019 3/15/2019 3/20/2019 3
US2309-2323 3/21/2019 3/15/2019 3/21/2019 4
US2309-2323 3/21/2019 3/15/2019 3/22/2019 5
Как вы можете видеть, какая дата [Last_Updated_On] будет возвращена для каждой строки, зависит от [Report_Date]. Здесь нужно сделать 3 проверки даты, чтобы определить, какую из них вернуть. 15.03.2009, 19.03.2009 и 21.03.2009. Должно быть понятно, почему даты [Last_Updated_On] являются такими, какие они есть.
[Report_Date] принимает только самую последнюю доступную дату [Last_Updated_On], которая меньше или равна самой себе. 3/18 строка вернет дату [Last_Updated_On] 3/15, поскольку 3/19 еще не произошло, и ее нельзя было обновить завтра днем ранее. 3/19, последний раз обновлялся в тот же день, поэтому теперь возвращается 3/19 для даты [Last_Updated_On]. То же самое для 3/20, так как [Last_Updated_On] Date использовал максимальный день, который меньше или равен [Report_Date]. 3/21 он был обновлен снова, поэтому теперь [Last_Updated_On] дата составляет 3/21 для [Report_date] 3/21 и 3 / 22.
Теперь для 3-го сценария, где дело разрешается где-то в середине диапазона [Report_Start_Date] и [Report_End_Date].
Данные на сервере:
[Case_ID] [Last_Updated_On] [Contact_Date] [Resolved_Date]
US2309-2323 3/15/2019 3/15/2019 3/21/2019
US2309-2323 3/19/2019 3/15/2019 3/21/2019
US2309-2323 3/21/2019 3/15/2019 3/21/2019
Query_Returns:
[Case_ID] [Last_Updated_On] [Contact_Date] [Report_Date] [Age]
US2309-2323 3/15/2019 3/15/2019 3/18/2019 1
US2309-2323 3/19/2019 3/15/2019 3/19/2019 2
US2309-2323 3/19/2019 3/15/2019 3/20/2019 3
US2309-2323 3/21/2019 3/15/2019 3/21/2019 4
Обратите внимание, что, хотя отчетные даты были установлены с 18.03.2009 по 22.03.2009, поскольку дело было решено 21.03.2009, по состоянию на 22.03.2009 строка не возвращается по состоянию на 21.03.2009 дело больше не было открыто.
Я надеюсь, что это подробно объясняет то, что я пытаюсь выполнить, и я знаю, что должен быть способ сделать это, но это действительно намного более сложный запрос, чем я когда-либо пытался. Я даже не знаю, с чего начать, поэтому любая помощь, которая может быть оказана, будет принята с благодарностью.
Вот некоторый SQL, чтобы помочь:
CREATE TABLE Open_Cases (
[Case_ID] varchar(15),
[Last_Updated_On] datetime,
[Contact_Date] datetime,
)
CREATE TABLE Resolved_Cases(
[Case_ID] varchar(15),
[Resolved_Date] datetime
)
INSERT INTO Open_Cases VALUES ('US2309-2323', '3/15/2019', '3/15/2019 ')
INSERT INTO Open_Cases VALUES ('US2309-2323', '3/19/2019', '3/15/2019 ')
INSERT INTO Open_Cases VALUES ('US2309-2323', '3/20/2019', '3/15/2019 ')
INSERT INTO Resolved_Cases VALUES ('US2309-2323', '3/21/2019')
DECLARE @Report_Start_Date date;
DECLARE @Reprot_End_Date date;
SET @Report_Start_Date = '3/18/2019';
SET @Report_End_Date = '3/22/2019';
BEGIN
WITH GetReportDate AS (
--***SQL Code to generate each day based on the start and end date range
),
SELECT o.Case_ID, o.Last_Updated_On, o.Contact_Date, r.Resolved_Date,
(SELECT CalcAge(@Report_Start_Date, @Report_End_Date) AS Age,
FROM Open_Cases AS o
LEFT JOIN Resolved_Cases as r
ON r.Case_ID = o.Case_ID
EXCEPT
SELECT r.Resolved_Date, FROM Resolved_Cases as r
LEFT JOIN GetReportDate as Rep
ON Rep.Report_Date > r.Resolved_Date
END
Это должно быть все необходимое, чтобы помочь с этой проблемой. Примечание. CalcAge - это скалярная табличная функция, возвращающая значение INT, которое дает нам количество дней между двумя датами, вычитающими выходные и выходные. Я не уверен, что CTE - это то, что я хочу создать для каждой Report_Date, основываясь на диапазоне дат начала и окончания, но я предполагаю, что это может сработать? Я знаю, что не могу сделать сравнение в операторе EXCEPT между Report_Date и Resolved_Date, потому что Report_Date - это вычисляемый столбец, и я знаю, что использование CTE позволит выполнить сравнение, но, опять же, я не уверен, что это правильный метод для получения это работает.
Также предполагаю, что я должен использовать Исключение, исходя из того, что значение report_date больше, чем Resolved_Date ... не стесняйтесь исправлять и / или изменять любое из этих операторов, так как я делаю все возможное, чтобы угадать, что должно произойти. ..посещение кем-то может заполнить остальное для меня.