Reputation: 186582
I have a rates
table which holds rows of nightly rates per day. I have a ratecodes
table which houses different ratecodes mapped to rates
.
My goal is to find any missing rates
for any days for an X period of time. For this example let's use 1 month.
Desired result: 64 rows of which 2 rows are filled with information with the first rate code. The second rate code has absolutely no rows in rates
but I need to show that it's actually missing dates. ( 64 because 1 month from now returns 32 days x 2 rate codes )
Two tables in question:
CREATE TABLE `ratecode` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ratecode` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `ratecode` VALUES ('1', 'BLAH');
INSERT INTO `ratecode` VALUES ('2', 'NAH');
CREATE TABLE `rates` (
`thedate` date DEFAULT NULL,
`rate` double DEFAULT NULL,
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ratecode` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `rates` VALUES ('2014-12-27', '999', '1', '1');
INSERT INTO `rates` VALUES ('2014-12-26', '99', '2', '1');
So using this query, in 2 parts. Part 1 is a temporary table of dates from today to 1 month ahead:
CREATE TEMPORARY TABLE IF NOT EXISTS `myDates` AS (
SELECT
CAST((SYSDATE()+INTERVAL (H+T+U) DAY) AS date) d
FROM ( SELECT 0 H
UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300
) H CROSS JOIN ( SELECT 0 T
UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30
UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60
UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90
) T CROSS JOIN ( SELECT 0 U
UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) U
WHERE
(SYSDATE()+INTERVAL (H+T+U) DAY) <= (SYSDATE()+INTERVAL 1 MONTH)
ORDER BY d ASC
);
And part 2 is the actual selection going on:
SELECT
*
FROM
rates
RIGHT JOIN myDates ON ( myDates.d = rates.thedate )
LEFT OUTER JOIN ratecode ON ( rates.ratecode = ratecode.id )
This returns only 32 rows back because in rates
, there are 2 records for the first entry in ratecode
. I don't get back the 32 missing rows for the other ratecode. How can I adjust in order to retain this information?
After I get the 64 rows back, I also need to filter for which ones are "blank" or haven't been entered in rates
. So missing values only.
Upvotes: 0
Views: 145
Reputation: 1270021
If I understand correctly, you want to generate all the rows using a cross join
, then left join
to the data and filter out all th ematches:
select rc.ratecode, d.d as missingdate
from ratecode rc cross join
mydates d left join
rates r
on rc.id = r.ratecode and d.d = r.thedate
where r.id is null;
Upvotes: 1