Get Results based on the latest date in a Joined table - sql

I have 2 tables tbl_job & tbl_appointment
I want to get all active jobs starting with job_refrence = '1%' also the latest active appointment.created_when and appointment_type associated with it ordered by the appointment.created_when
A job can have many appointments
If all the appointments associated with the job has deleted_flag = 1
then the resultset should return tbl_job.created-when as the
latest_appointment_date
CREATE TABLE [dbo].[tbl_job]
(
[job_id] UNIQUEIDENTIFIER NOT NULL,
[account_id] INT NOT NULL,
[description] NVARCHAR(1024) NULL,
[deleted_flag] BIT NOT NULL,
[created_when] DATETIME2 (6) NOT NULL,
[job_reference] NVARCHAR(15) NOT NULL
)
CREATE TABLE [dbo].[tbl_appointment]
(
[appointment_id] UNIQUEIDENTIFIER NOT NULL,
[job_id] UNIQUEIDENTIFIER NOT NULL,
[deleted_flag] BIT NOT NULL,
[appointment_type] NVARCHAR(35) NOT NULL,
[created_when] DATETIME2 (6) NOT NULL,
[account_id] INT NULL,
)
insert into dbo.tbl_job (job_id, account_id, [description], deleted_flag, created_when, job_reference) values
('A29A6381-EF0D-47F6-BFC3-051679E343D0', 1, 'descr1', 0, '2020-06-12 00:58:17.7221410', 1 )
,('4D8C1B04-9E00-41FA-BDB8-653C26712144', 1, 'descr2', 0, '2020-06-10 00:58:17.7221410', 12 )
,('F8DC690E-74AB-46F4-90D3-55E032F21C99', 1, 'descr3', 0, '2020-06-26 00:58:17.7221410', 123 )
,('C5D8AA45-FA45-41A4-877D-5B803C1BE61B', 1, 'descr4', 0, '2020-06-27 00:58:17.7221410', 76 )
insert into dbo.tbl_appointment(appointment_id, job_id, deleted_flag, appointment_type, created_when, account_id) Values
('9E24451F-5703-414F-ACF1-9304AFBEA8F1', 'A29A6381-EF0D-47F6-BFC3-051679E343D0', 0, 'job1_cat1', '2020-06-12 00:58:17.7221410', 1)
,('A8121DC1-271E-4BD0-A6AA-D753CF4D310E', 'A29A6381-EF0D-47F6-BFC3-051679E343D0', 0, 'job1_cat2', '2020-06-14 00:58:17.7221410', 1)
,('61ED5B48-DF95-4FC8-AF1D-1418C6DD9088', '4D8C1B04-9E00-41FA-BDB8-653C26712144', 0, 'job2_cat1', '2020-06-15 00:58:17.7221410', 1)
,('0e4fc735-96c3-4cab-8ade-796bae4639d1', 'F8DC690E-74AB-46F4-90D3-55E032F21C99', 1, 'job3_cat1', '2020-06-28 00:58:17.7221410', 1)
Expected ResultSet
job_id job_reference latest_appointment_date appointment_type total_rows
F8DC690E-74AB-46F4-90D3-55E032F21C99 123 2020-06-26 00:58:17.722141 NULL 3
4D8C1B04-9E00-41FA-BDB8-653C26712144 12 2020-06-15 00:58:17.722141 job2_cat1 3
A29A6381-EF0D-47F6-BFC3-051679E343D0 1 2020-06-14 00:58:17.722141 job1_cat2 3
Below query works, but its not an efficient as we have millions of rows in the tables. I would like to replace the OUTER apply with a Left join or some other way to make it more efficient
DECLARE #filtered_jobs TABLE
(
job_domain_id UNIQUEIDENTIFIER
,job_reference NVARCHAR(15)
,job_created_when DATETIME2(6)
,latest_appointment_date DATETIME2(6)
,appointment_type NVARCHAR(35)
);
declare #account_id int = 1
declare #job_reference nvarchar(35) = '1'
declare #offset int = 0
declare #limit int = 10
declare #is_sort_ascending int = 0
INSERT INTO #filtered_jobs (job_domain_id, job_reference, job_created_when, latest_appointment_date,appointment_type)
SELECT
j.job_id
,j.job_reference
,j.created_when
,ap.created_when AS latest_appointment_date
,ap.appointment_type
FROM dbo.tbl_job j
OUTER APPLY (
SELECT TOP (1) ap.appointment_type,ap.created_when,ap.deleted_flag
FROM dbo.tbl_appointment ap
WHERE ap.job_id = j.job_id AND ap.deleted_flag = 0
ORDER BY ap.created_when desc
) ap
WHERE j.account_id = #account_id
AND j.job_reference LIKE (#job_reference + '%')
AND j.deleted_flag = 0
SELECT
fj.job_domain_id
,fj.job_reference
,ISNULL(fj.latest_appointment_date,fj.job_created_when) AS latest_appointment_date
,fj.appointment_type
FROM #filtered_jobs fj
ORDER BY
CASE WHEN #is_sort_ascending = 0 THEN ISNULL(fj.latest_appointment_date,fj.job_created_when) END DESC,
CASE WHEN #is_sort_ascending = 1 THEN ISNULL(fj.latest_appointment_date,fj.job_created_when) END ASC
OFFSET #offset ROWS FETCH NEXT #limit ROWS ONLY;
SELECT COUNT(1) AS total_records
FROM #filtered_jobs;

You could use a ranking function but you need to test whether it is faster:
From the query you posted, replace the insert into #filtered_jobs with these 2:
INSERT INTO #filtered_jobs (job_domain_id, job_reference, job_created_when)
select j.job_id
,j.job_reference
,j.created_when
FROM dbo.tbl_job j
WHERE j.account_id = #account_id
AND j.job_reference LIKE (#job_reference + '%')
AND j.deleted_flag = 0
update f
set latest_appointment_date=x.latest_appointment_date,
appointment_type=x.appointment_type
from #filtered_jobs f
inner join (
select f.job_domain_id
,ap.created_when AS latest_appointment_date
,ap.appointment_type as appointment_type
, rank() over (partition by ap.job_id order by ap.created_when desc) rnk
from #filtered_jobs f
inner join dbo.tbl_appointment ap on ap.job_id = f.job_domain_id
where ap.deleted_flag = 0) x on f.job_domain_id=x.job_domain_id
where x.rnk=1
Make sure you have a index on dbo.tbl_appointment(column job_id, ap.deleted_flag), preferably including (created_when, appointment_type) if this query is ran alot.

Related

T-SQL - Query data based on different filter granularity

-- Data Setup
DECLARE #Table AS TABLE
(
[Id] INT IDENTITY(1, 1)
, [Type] TINYINT
, [TypeOne] INT
, [TypeTwo] INT
, [TypeThree] INT
) ;
INSERT INTO #Table
( [Type]
, [TypeOne]
, [TypeTwo]
, [TypeThree] )
VALUES
( 1, 1, NULL, NULL )
, ( 1, 2, NULL, NULL )
, ( 1, 3, NULL, NULL )
, ( 2, NULL, 10, NULL )
, ( 2, NULL, 20, NULL )
, ( 3, NULL, NULL, 100 )
, ( 3, NULL, NULL, 200 )
, ( 3, NULL, NULL, 300 ) ;
-- Query filters
DECLARE #IncludeTypeOne BIT = 1
, #IncludeTypeTwo BIT = 0 ;
DECLARE #TypeThree_Ids TABLE ( [TypeThree] INT ) ;
INSERT INTO #TypeThree_Ids
VALUES
( 200 )
, ( 300 ) ;
-- Goal: To query #Table based on #IncludeTypeOne, #IncludeTypeTwo, and #TypeThree_Ids values. For first two filters, there's no need to check for specific value of the type in the [TypeOne] and [TypeTwo] columns. However, for the third filter, specific values in the [TypeThree] column must match with the values in #TypeThree_Ids. Is there a way to do this without doing three separate queries and union-ing them all together (the actual table/data is quite large)?
-- Expected output
Id Type TypeOne TypeTwo TypeThree
1 1 1 NULL NULL
2 1 2 NULL NULL
3 1 3 NULL NULL
7 3 NULL NULL 200
8 3 NULL NULL 300
-- My unsuccessful try thus far
SELECT *
FROM #Table
WHERE ( ( #IncludeTypeOne = 0 AND [Type] <> 1 ) OR [Type] = 1 )
AND ( ( #IncludeTypeTwo = 0 AND [Type] <> 2 ) OR [Type] = 2 )
AND ( ( ( SELECT COUNT(1) FROM #TypeThree_Ids ) = 0 AND [Type] <> 3 ) OR [TypeThree] IN ( SELECT [TypeThree] FROM #TypeThree_Ids ) ) ;
-- Actual output
Id Type TypeOne TypeTwo TypeThree
Better to use a join than a sub query -- like this:
SELECT *
FROM #Table
LEFT JOIN #TypeThreeIds ON #Table.TypeThree= #TypeThreeIds.TypeThree
WHERE (#includetypeone = 1 AND [Type] = 1)
OR (#includetypetype = 2 AND [Type] = 2)
OR ([Type] = 3 AND #TypeThreeIds.TypeThree IS NOT NULL)

sql SERVER - distinct selection based on priority columns

hello I would like to find a solution to solve my problem in a single request if possible.
For the moment I take all the records then I go through the lines one by one to eliminate what I don't want.
I have 2 tables : first table with links
the second with the prefered label for the url
the second table must be consulted keeping only the row with maximum priority
priority rules are
the current user then
the user group and finally
everyone.
if the hidden column is true, exclude any reference to the url
here is the expected result.
Unfortunately, I don't see any other solution than to multiply the conditions on several selects and unions.
if you have a idea to solve my problem, thank you in advance for your help
It appears as though you can rely on pref_id for the preference ordering, correct? If so, you could try:
SELECT *
FROM table2
INNER JOIN table1 ON table2.url_id = table1.url_id
QUALIFY ROW_NUMBER() OVER (
PARTITION BY table1.url
ORDER BY pref_id ASC
) = 1
This will partition by the url and then provide only the one with lowest pref_id.
I didn't test this SQL as I wasn't sure which RDBMS you're running on, but I used Rasgo to translate the SQL.
maybe of interest in this tricky query:
select so.*, table1.url from
(select distinct t.url_id,
(select pref_id from table2 s where s.url_id = t.url_id order by "user" is null, "group" is null limit 1) pref_id
from table2 t
where not exists(select 1 from table2 s where s.hide and s.url_id = t.url_id)
) ids
join table2 so on so.pref_id = ids.pref_id
join table1 ON table1.url_id = ids.url_id
order by so.url_id;
here is my solution but i think there is better to do.
in the condition's select, I built a column which gives a level note according to the priorities
DECLARE #CUR_USER VARCHAR(10) = 'ROBERT'
DECLARE #CUR_GROUP VARCHAR(10) = 'DEV'
DECLARE #TABLE1 TABLE (
URL_ID INT
,URLNAME VARCHAR(100)
);
DECLARE #TABLE2 TABLE (
PREF_ID INT
,URL_ID INT
,FAVORITE_LABEL VARCHAR(100)
,USER_GROUP VARCHAR(10)
,USER_CODE VARCHAR(10)
,HIDE_URL DECIMAL(1, 0) DEFAULT 0
);
INSERT INTO #TABLE1
VALUES
(1, 'https://stackoverflow.com/')
,(2, 'https://www.microsoft.com/')
,(3, 'https://www.apple.com/')
,(4, 'https://www.wikipedia.org/')
;
INSERT INTO #TABLE2
VALUES
(1000, 1, 'find everything', NULL, 'ROBERT', 0)
,(1001, 1, 'a question ? find the answer here', 'DEV', NULL, 0)
,(1002, 1, 'StackOverFlow', NULL, NULL, 0)
,(1003, 2, 'Windows', 'DEV', NULL, 0)
,(1004, 2, 'Microsoft', NULL, NULL, 0)
,(1005, 3, 'Apple', NULL, NULL, 0)
,(1006, 4, 'Free encyclopedia', NULL, 'ROBERT', 1)
,(1007, 4, 'Wikipedia', NULL, NULL, 0)
,(1008, 1, 'StackOverFlow FOR MAT', 'MAT', NULL, 0)
,(1009, 2, 'Microsoft FOR MAT', 'MAT', NULL, 0)
,(1010, 3, 'Apple', 'MAT', NULL, 1)
,(1011, 4, 'Wikipedia FOR MAT', 'MAT', NULL, 0)
,(1012, 1, 'StackOverFlow', NULL, 'JEAN', 1)
,(1013, 2, 'Microsoft ', NULL, 'JEAN', 0)
,(1014, 3, 'Apple', NULL, 'JEAN', 0)
,(1015, 4, 'great encyclopedia', NULL, 'JEAN', 0)
;
SELECT t2.* ,t1.URLName
FROM #TABLE1 t1
INNER JOIN #TABLE2 t2 ON t1.URL_ID = t2.URL_ID
WHERE EXISTS (
SELECT 1
FROM (
SELECT TOP (1) test.PREF_ID
,CASE
-- if I do not comment this case: jean from the MAT group will not see apple
-- WHEN Hide_Url = 1
-- THEN 3
WHEN USER_code IS NOT NULL
THEN 2
WHEN USER_GROUP IS NOT NULL
THEN 1
ELSE 0
END AS ROW_LEVEL
FROM #TABLE2 test
WHERE (
(
test.USER_GROUP IS NULL
AND test.user_group IS NULL
AND test.USER_code IS NULL
)
OR (test.USER_GROUP = #CUR_GROUP)
OR (test.USER_code = #CUR_USER)
)
AND t2.URL_ID = test.URL_ID
ORDER BY ROW_LEVEL DESC
) test
WHERE test.PREF_ID = t2.PREF_ID
AND Hide_Url = 0
)
Simply use an ORDER BY clause that puts the preferred row first. You can use this in the window function ROW_NUMBER and work with this or use a lateral top(1) join with CROSS APPLY.
select *
from urls
cross apply
(
select top(1) *
from labels
where labels.url_id = urls.url_id
where [Group] is not null or [user] is not null or hide is not null
order by
case when [Group] is null then 2 else 1 end,
case when [user] is null then 2 else 1 end,
case when hide is null then 2 else 1 end
) top_labels
order by urls.url_id;

Get the id of the last record in the data SQL Server

I am trying to get the last ID from at least 4 child-parent relationships between ID's and sum all related ID's quantity. I have tried below -
declare #test table (ID int not null, P_ID int null, Qty int not null)
insert into #test(ID, P_ID, Qty) values
(1 , 11 , 1),
(2 , null, 3),
(11, 21 , 2),
(21, 31 , 1),
(31, null, 3),
(12, null, 4)
select
COALESCE(T2.ID,T1.ID) as ID,
MAX(CASE WHEN T1.P_ID is not null then T1.ID END) as OldID,
SUM(Qty) as Qty
from
#test T1
left join
(select ID from #test
GROUP By ID) T2
on T2.ID = T1.P_ID
group by
COALESCE(T2.ID, T1.ID)
I am getting output -
ID OldID Qty
2 NULL 3
11 1 1
12 NULL 4
21 11 1
31 21 2
But I want my output will be like this where all ID's with no Parent ID in the first row then all previous ID's will show and SUM all relevant ID's quantity -
ID OldID3 OldID2 OldID1 Qty
2 3
12 4
31 21 11 1 7
Could someone please help me to achieve this.
Thanks in advance
Hopefully, this helps you. I have not tested it thoroughly, so apologies for any bugs.
I'm using a Common Table Expression to get the hierarchy information, then using a dynamic SQL I extract the desired number of previous IDs.
DECLARE #test TABLE (ID INT NOT NULL, P_ID INT NULL, Qty INT NOT NULL);
INSERT INTO #test(ID, P_ID, Qty) VALUES
(1 , 11 , 1),
(2 , null, 3),
(11, 21 , 2),
(21, 31 , 1),
(31, null, 3),
(12, null, 4);
IF (OBJECT_ID('tempdb..#hierarchy') IS NOT NULL)
DROP TABLE #hierarchy;
CREATE TABLE #hierarchy (
RootID INT NOT NULL, ID INT NOT NULL, [Qty] INT NOT NULL, SeqIndex INT NOT NULL
);
;WITH hierarchy AS (
SELECT ID, P_ID, Qty, ID [RootID], 0 [SeqIndex]
FROM #test
WHERE P_ID IS NULL
UNION ALL
SELECT child.ID, child.P_ID, child.Qty, parent.RootID, parent.SeqIndex + 1 [SeqIndex]
FROM #test child
JOIN hierarchy parent ON parent.ID=child.P_ID
)
INSERT #hierarchy
SELECT RootID, ID, Qty, SeqIndex
FROM hierarchy;
DECLARE
#DEPTH INT = 3,
#maxSeqIndex INT = (SELECT MAX(SeqIndex) FROM #hierarchy);
IF (#DEPTH = 0)
SELECT RootID, SUM(Qty) [Qty]
FROM #hierarchy
GROUP BY RootID;
ELSE IF (#DEPTH > #maxSeqIndex)
SELECT NULL
ELSE BEGIN
DECLARE #SQL NVARCHAR(MAX) = N'
SELECT
RootID,
';
DECLARE #idx INT = 1;
WHILE #idx <= #DEPTH BEGIN
SET #SQL += N'
(SELECT ID FROM #hierarchy i WHERE i.RootID=o.RootID AND SeqIndex='+CAST(#idx as nvarchar(10))+N') [OldID'+CAST(#maxSeqIndex-#idx+1 as nvarchar(10))+N'],';
SET #idx += 1;
END
SET #SQL += N'
SUM(Qty) [Qty]
FROM #hierarchy o
GROUP BY RootID;';
EXEC sp_executesql #SQL
END
Of course, the dynamic script could be replaced with a hard-coded SQL if that is OK for you.
Note: performance has not been considered

Looping through groups of records

SQL Server 2014, I have a table with a number of rows for example 15, 5 have a groupid column of 736881 and 10 have a group id column 3084235. What I want to do is process each group of records in turn and load the results in to a table.
I have written the code to do this but I think I am not setting the loopcounter incorrectly set as I keep getting the groupid of records 736881 loaded twice.
I cant't currently post the test data due to containing personal information but if the mistake is not obvious I will try and create some dummy data.
SELECT #LoopCounter = min(rowfilter) , #maxrowfilter = max(rowfilter)
FROM peops6
WHILE ( #LoopCounter IS NOT NULL
AND #LoopCounter <= #maxrowfilter)
begin
declare #customer_dist as Table (
[id] [int] NOT NULL,
[First_Name] [varchar](50) NULL,
[Last_Name] [varchar](50) NULL,
[DoB] [date] NULL,
[post_code] [varchar](50) NULL,
[mobile] [varchar](50) NULL,
[Email] [varchar](100) NULL );
INSERT INTO #customer_dist (id, First_Name, Last_Name, DoB, post_code, mobile, Email)
select id, first_name, last_name, dob, postcode, mobile_phone, email from peops6 where rowfilter = #LoopCounter
insert into results
SELECT result.* ,
[dbo].GetPercentageOfTwoStringMatching(result.DoB, d.DoB) [DOB%match] ,
[dbo].GetPercentageOfTwoStringMatching(result.post_code, d.post_code) [post_code%match] ,
[dbo].GetPercentageOfTwoStringMatching(result.mobile, d.mobile) [mobile%match] ,
[dbo].GetPercentageOfTwoStringMatching(result.Email, d.Email) [email%match]
FROM ( SELECT ( SELECT MIN(id)
FROM #customer_dist AS sq
WHERE sq.First_Name = cd.First_Name
AND sq.Last_Name = cd.Last_Name
AND ( sq.DoB = cd.DoB
OR sq.mobile = cd.mobile
OR sq.Email = cd.Email
OR sq.post_code = cd.post_code )) nid ,
*
FROM #customer_dist AS cd ) AS result
INNER JOIN #customer_dist d ON result.nid = d.id order by 1, 2 asc;
SELECT #LoopCounter = min(rowfilter) FROM peops6
WHERE rowfilter > #LoopCounter
end
You need to truncate your table variable (#customer_dist) at the end of the loop:
....
-- Add this
TRUNCATE TABLE #customer_dist
SELECT #LoopCounter = min(rowfilter) FROM peops6
WHERE rowfilter > #LoopCounter
end
See: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/42ef20dc-7ad8-44f7-b676-a4596fc0d593/declaring-a-table-variable-inside-a-loop-does-not-delete-the-previous-data?forum=transactsql
I am not sure you need a LOOP like using a SQL Cursor to fulfill this task
Please check following SQL statement where I used multiple CTE expressions
with customer_dist as (
select
rowfilter,
id, first_name, last_name, dob, postcode, mobile_phone, email
from peops6
), result as (
SELECT
(
SELECT
MIN(id)
FROM customer_dist AS sq
WHERE
sq.rowfilter = cd.rowfilter
AND sq.First_Name = cd.First_Name
AND sq.Last_Name = cd.Last_Name
AND (sq.DoB = cd.DoB OR sq.mobile_phone = cd.mobile_phone OR sq.Email = cd.Email OR sq.postcode = cd.postcode )
) nid,
*
FROM customer_dist AS cd
)
SELECT
result.* ,
[dbo].edit_distance(result.DoB, d.DoB) [DOB%match] ,
[dbo].edit_distance(result.postcode, d.postcode) [post_code%match] ,
[dbo].edit_distance(result.mobile_phone, d.mobile_phone) [mobile%match] ,
[dbo].edit_distance(result.Email, d.Email) [email%match]
FROM result
INNER JOIN customer_dist d
ON result.nid = d.id
order by 1, 2 asc;
Please note, I used my fuzzy string matching Levenshtein Distance Algorithm in this sample instead of your function
And the outcome is as follows
Only you need to add the INSERT statement just before the last SELECT statement
Hope it is useful

Select nearest date on the basis of ID in SQL

I have two table Dispense & Pro Table, I want to select all rows from Dispense table and nearest Shipment date from Pro table.
Dispense Table
ID Dispense date Row ID
604743 10/18/2016 1
604743 11/4/2016 2
604743 11/28/2016 3
604743 12/16/2016 4
Pro table
ID Shipment Date Row ID
604743 11/1/2016 1
604743 11/19/2016 2
604743 11/21/2016 3
604743 11/28/2016 4
604743 12/13/2016 5
Output Needed
ID Dispense date Pre Ship date
604743 10/18/2016 NULL
604743 11/4/2016 11/1/2016
604743 11/28/2016 11/19/2016
604743 12/16/2016 12/13/2016
Reason for NULL: Because less than 10/18 dispense date no nearest date in Shipping date in Pro Table
I tried with recursive CTE, but they don't all to use the anchor in a subquery.
So a while-loop is the best I could do.
The script allows for several Dispense or Pro at same date, see the comments on which part you can throw out if that is not allowed by constraints.
--- Dispense_Date must not be unique
declare #Dispense table(
ID int not null,
Dispense_Date date not null,
Row_ID int not null identity primary key
)
-- Shipment_Date must not be unique
declare #Pro table(
ID int not null,
Shipment_Date date not null,
Row_ID int not null identity primary key
)
declare #Result table(
ID int not null,
Dispense_Date date not null,
Dispense_Row_ID int not null unique,
Shipment_Date date not null,
Pro_Row_ID int not null unique,
dayDiff int not null,
Row_ID int not null identity primary key,
iter int not null
)
insert into #Dispense(ID, Dispense_Date)
values (604743, '10/18/2016'),
(604743, '11/4/2016'),
/* (604743, '11/26/2016'),
(604743, '11/27/2016'),
(604743, '11/27/2016'),
(604743, '11/28/2016'), */
(604743, '11/28/2016'),
(604743, '12/16/2016')
insert into #Pro(ID, Shipment_Date)
values (604743, '11/1/2016'),
/* (604743, '11/16/2016'),
(604743, '11/19/2016'), */
(604743, '11/19/2016'),
(604743, '11/21/2016'),
(604743, '11/28/2016'),
(604743, '12/13/2016')
declare #iter int = 0
while exists(
select 1
from #Dispense Dispense
inner join
#Pro Pro
on Pro.ID = Dispense.ID
and
Pro.Shipment_Date < Dispense.Dispense_Date
where not exists(
select 1
from #Result Result
where Result.Dispense_Row_ID = Dispense.Row_ID
or
Result.Pro_Row_ID = Pro.Row_ID
)
)
begin
set #iter = #iter + 1
;
with distance(
ID, Dispense_Row_ID, Dispense_Date, Pro_Row_ID, Shipment_Date, dayDiff
) as(
select Dispense.ID,
Dispense.Row_ID Dispense_Row_ID,
Dispense.Dispense_Date,
Pro.Row_ID Pro_Row_ID,
Pro.Shipment_Date,
DATEDIFF(DAY, Pro.Shipment_Date, Dispense.Dispense_Date) dayDiff
from #Dispense Dispense
inner join
#Pro Pro
on Pro.ID = Dispense.ID
and
Pro.Shipment_Date < Dispense.Dispense_Date
where not exists(
select 1
from #Result Result
where Result.Dispense_Row_ID = Dispense.Row_ID
or
Result.Pro_Row_ID = Pro.Row_ID
)
)
insert into #Result(ID, Dispense_Row_ID, Dispense_Date, Pro_Row_ID, Shipment_Date, daydiff, iter)
select Dispense.ID,
Dispense.Row_ID Dispense_Row_ID,
Dispense.Dispense_Date,
distance.Pro_Row_ID,
distance.Shipment_Date,
distance.dayDiff,
#iter
from #Dispense Dispense
inner join
distance
on distance.Dispense_Row_ID = Dispense.Row_ID
and
not exists(
select 1
from distance dtExists
where dtExists.ID = distance.ID
and
dtExists.Shipment_Date = distance.Shipment_Date
and
(
dtExists.dayDiff < distance.dayDiff
-- below OR not needed if Dispense_Date and Shipment_Date are unique
or
(
dtExists.dayDiff = distance.dayDiff
and
(
dtExists.Pro_Row_ID < distance.Pro_Row_ID
or
(
dtExists.Pro_Row_ID = distance.Pro_Row_ID
and
dtExists.Dispense_Row_ID < distance.Dispense_Row_ID
)
)
)
)
)
and
not exists(
select 1
from distance dtExists
where dtExists.ID = distance.ID
and
dtExists.Dispense_Date = distance.Dispense_Date
and
(
dtExists.dayDiff < distance.dayDiff
-- below OR not needed if Dispense_Date and Shipment_Date are unique
or
(
dtExists.dayDiff = distance.dayDiff
and
(
dtExists.Pro_Row_ID < distance.Pro_Row_ID
or
(
dtExists.Pro_Row_ID = distance.Pro_Row_ID
and
dtExists.Dispense_Row_ID < distance.Dispense_Row_ID
)
)
)
)
)
end
select Dispense.ID,
Dispense.Row_ID Dispense_Row_ID,
Dispense.Dispense_Date,
Result.Pro_Row_ID,
Result.Shipment_Date,
Result.dayDiff,
Result.iter
from #Dispense Dispense
left join
#Result Result
on Result.Dispense_Row_ID = Dispense.Row_ID
order by Dispense.ID,
Dispense.Dispense_Date,
Result.Shipment_Date,
Result.Dispense_Row_ID,
Result.Pro_Row_ID