I would like to know if it’s possible to join tables into a custom set of values in MySQL. For example, I have a set of dates (outside the database). I would like to get the matched joins in a single query so that I can easily loop through the result. Like:
Data outside database
Date |
---|
2021-04-08 |
2021-04-09 |
2021-04-10 |
2021-04-11 |
2021-04-12 |
The Database may look like
Table: transactions
id | date | amount |
---|---|---|
1 | 2021-04-08 | 500 |
2 | 2021-04-08 | 600 |
3 | 2021-04-10 | 350 |
I want the result to be like:
Date | Sum |
---|---|
2021-04-08 | 1100 |
2021-04-09 | 0 |
2021-04-10 | 350 |
2021-04-11 | 0 |
2021-04-12 | 0 |
In other words, I want to do:
SELECT transactions.date, SUM(amount) FROM ["2021-04-08", "2021-04-09", "2021-04-10", ...] INNER JOIN transactions ON current_value=transactions.date GROUP BY transactions.date
Advertisement
Answer
Example:
CREATE TABLE transactions (id INT, `date` DATE, amount INT); INSERT INTO transactions VALUES (1, '2021-04-08', 500), (2, '2021-04-08', 600), (3, '2021-04-10', 350); SELECT * FROM transactions;id | date | amount -: | :--------- | -----: 1 | 2021-04-08 | 500 2 | 2021-04-08 | 600 3 | 2021-04-10 | 350
SET @outside := '2021-04-08,2021-04-09,2021-04-10,2021-04-11,2021-04-12';
WITH RECURSIVE cte AS ( SELECT SUBSTRING_INDEX(@outside, ',', 1) `date`, TRIM(LEADING ',' FROM TRIM(LEADING SUBSTRING_INDEX(@outside, ',', 1) FROM @outside)) slack UNION ALL SELECT SUBSTRING_INDEX(slack, ',', 1), TRIM(LEADING ',' FROM TRIM(LEADING SUBSTRING_INDEX(slack, ',', 1) FROM slack)) FROM cte WHERE slack != '' ) SELECT `date`, COALESCE(SUM(transactions.amount), 0) `sum` FROM cte LEFT JOIN transactions USING (`date`) GROUP BY `date` ORDER BY `date`date | sum :--------- | ---: 2021-04-08 | 1100 2021-04-09 | 0 2021-04-10 | 350 2021-04-11 | 0 2021-04-12 | 0
SELECT `date`, COALESCE(SUM(transactions.amount), 0) `sum` FROM JSON_TABLE(CONCAT('["', REPLACE(@outside, ',', '","'), '"]'), "$[*]" COLUMNS (`date` DATE path "$")) jsontable LEFT JOIN transactions USING (`date`) GROUP BY `date` ORDER BY `date`date | sum :--------- | ---: 2021-04-08 | 1100 2021-04-09 | 0 2021-04-10 | 350 2021-04-11 | 0 2021-04-12 | 0
db<>fiddle here