Reputation: 5
I need to make a query
I have two tables, TableA and TableB
TableA is as following:
Id | Name |
---|---|
1 | Car |
2 | Plane |
3 | Ship |
4 | Bike |
5 | Skate |
And my TableB is like the following:
ID | MyDate | FID |
---|---|---|
1 | 29-08-2021 | 1 |
2 | 29-08-2021 | 2 |
3 | 29-08-2021 | 3 |
4 | 30-08-2021 | 1 |
5 | 30-08-2021 | 5 |
FID: is the column that relates TableB to TableA.
So, I need to show every record of TableA, with the records of TableB.
I know how to do it with a single Date. Some Like this:
SELECT ID, NAME, MyDATE
FROM TableA
LEFT JOIN TableB ON FID = ID AND MyDate = SomeDate
ORDER BY ID
If SomeDate = '29-08-2021'
That query should return the following result:
ID | Name | MyDate |
---|---|---|
1 | Car | 29-08-2021 |
2 | Plane | 29-08-2021 |
3 | Ship | 29-08-2021 |
4 | Bicicle | NULL |
5 | Skate | NULL |
If SomeDate = '30-08-2021', It should show the following
ID | Name | MyDate |
---|---|---|
1 | Car | 30-08-2021 |
2 | Plane | NULL |
3 | Ship | NULL |
4 | Bicicle | NULL |
5 | Skate | 30-08-2021 |
So, What I need is to give two dates, and print Everything in that range of dates, all the records of TableA with their corresponding records of TableB
So if I give the Dates 28-08-2021 to 30-08-2021, the result should be like the following
ID | Name | MyDate |
---|---|---|
1 | Car | NULL |
2 | Plane | NULL |
3 | Ship | NULL |
4 | Bicicle | NULL |
5 | Skate | NULL |
1 | Car | 29-08-2021 |
2 | Plane | 29-08-2021 |
3 | Ship | 29-08-2021 |
4 | Bicicle | NULL |
5 | Skate | NULL |
1 | Car | 30-08-2021 |
2 | Plane | NULL |
3 | Ship | NULL |
4 | Bicicle | NULL |
5 | Skate | 30-08-2021 |
I need to make a query that returns this result set.
The first 5 records, are the records corresponding to 28-09-2021, because there are no recoreds in TableB with that date, it returns null.
Because there are three dates, it should repeat all the records of table A three times.
I tried to do this
SELECT ID, NAME, MyDATE
FROM TableA
LEFT JOIN TableB ON FID = ID AND MyDate BETWEEN StartDate AND EndDate
ORDER BY ID
But doing that only returns 5 records (the first 3 with the date 29-08-2021, and the second 2 with the date 30-08-201).
I need to know how to do a query that returns result set I provided.
Upvotes: 0
Views: 821
Reputation: 3166
What you seem to want to do is get the cartesian product of TableA with all the dates in the date range. And then add information on each row as to if there is a corresponding row in your TableB.
You can start with a simple recursive SQL, that gets your dates:
WITH cte_dates(theDates)
AS (
SELECT @startdate
UNION ALL
SELECT DATEADD(day, 1, thedates)
FROM cte_dates
WHERE thedates < @enddate
)
SELECT *
FROM cte_dates;
This will result in:
thedates |
---|
2021-08-28 |
2021-08-29 |
2021-08-30 |
The variable declarations are:
DECLARE @startdate DATE;
DECLARE @enddate DATE;
SET @startdate = '2021-08-28';
SET @enddate = '2021-08-30';
Then join that with your TableA using WHERE 1 = 1
to get the cartesian product:
WITH cte_dates(thedates)
AS (
SELECT @startdate
UNION ALL
SELECT DATEADD(day, 1, thedates)
FROM cte_dates
WHERE thedates < @enddate
)
SELECT *
FROM TableA
JOIN cte_dates ON (1 = 1)
;
This will give you 15 rows where each row in TableA has an extra column with the date. Each original row in TableA will result in 3 rows in this result set, since there are 3 dates.
Now you can use a outer left join to get the corresponding TableB values:
WITH cte_dates(thedates)
AS (
SELECT @startdate
UNION ALL
SELECT DATEADD(day, 1, thedates)
FROM cte_dates
WHERE thedates < @enddate
)
SELECT ta.id, ta.name, tb.mydate
FROM TableA AS ta
JOIN cte_dates AS dat ON (1 = 1)
LEFT JOIN TableB AS tb ON tb.fid = ta.id
AND tb.mydate = dat.thedates
;
Upvotes: 1