Reputation: 61
I want to fill in dates that are missing from one table from the dates table that I created.
The first table where i have all the dates is this one:
Dates
01/11/2018
02/11/2018
03/11/2018
The second table with my data is this one:
Name Value Date
Go 1 01/11/2018
Go 3 02/11/2018
Ma 2 03/11/2018
My final output should be like this:
Name Value Date
Go 1 01/11/2018
Go 3 02/11/2018
Go null 03/11/2018
Ma null 01/11/2018
Ma null 02/11/2018
Ma 2 03/11/2018
I tried a full outer join and it didn't work:
select b.name, a.d_date, b.value
from date_month a
full outer join namevalue b on a.d_date=b.d_date;
datemonth is the table with the dates and namevalue is the table with the names. The table with the names has at least 300,000 names in with dates and values.
Upvotes: 3
Views: 4753
Reputation: 36817
A partitioned-outer join is a great way to fill gaps in sparse data. This join lets us repeat a join, based on the values in a column. This approach joins more than a regular outer join, but much less than a cross join, and it should be more efficient than a cross join solution.
select name, value, dates.the_date
from dates
left join my_data
partition by (my_data.name)
on dates.the_date = my_data.the_date
order by name, the_date;
NAME VALUE THE_DATE
---- ----- --------
Go 1 2018-01-11
Go 3 2018-02-11
Go 2018-03-11
Ma 2018-01-11
Ma 2018-02-11
Ma 2 2018-03-11
Sample schema:
create table dates as
select date '2018-01-11' the_date from dual union all
select date '2018-02-11' the_date from dual union all
select date '2018-03-11' the_date from dual;
create table my_data as
select 'Go' name, '1' value, date '2018-01-11' the_date from dual union all
select 'Go' name, '3' value, date '2018-02-11' the_date from dual union all
select 'Ma' name, '2' value, date '2018-03-11' the_date from dual;
Upvotes: 2
Reputation: 3225
Tried on SQLite3 (adjust accordingly, if needed).
-- setup test tables & data
create table Dates(d);
insert into dates values
('2018-11-01'),
('2018-11-02'),
('2018-11-03');
--The second table with my data is this one
create table dat(name,val,d);
insert into dat values
('Go',1,'2018-11-01'),
('Go',3,'2018-11-02'),
('Ma',2,'2018-11-03');
and the query is:
select name,val,d
from (select distinct name,dates.d from dat join dates)
left join dat using(name,d);
Upvotes: 0
Reputation: 272106
You need to use CROSS JOIN
to create a result consisting of 2 names x 3 dates = 6 rows. Then do a LEFT JOIN
:
SELECT all_names.name, date_month.date, namevalue.value
FROM (SELECT DISTINCT name FROM namevalue) AS all_names
CROSS JOIN date_month
LEFT JOIN namevalue ON all_names.name = namevalue.name
AND date_month.date = namevalue.date
Upvotes: 2