Reputation: 5471
/* Sales */
CREATE TABLE sales (
id int auto_increment primary key,
category VARCHAR(255),
sales_date DATE,
sales_volume INT
);
INSERT INTO sales
(category, sales_date, sales_volume
)
VALUES
("Category_01", "2020-01-03", "500"),
("Category_01", "2020-04-15", "700"),
("Category_01", "2020-08-27", "180"),
("Category_01", "2020-09-29", "320"),
("Category_02", "2020-07-17", "420"),
("Category_02", "2020-12-24", "350"),
("Category_02", "2020-12-08", "570"),
("Category_03", "2020-01-10", "180"),
("Category_03", "2020-10-20", "970");
/* Return Risk */
CREATE TABLE return_risk (
id int auto_increment primary key,
category VARCHAR(255),
quarter VARCHAR(255),
return_risk_rate DECIMAL(5,2)
);
INSERT INTO return_risk
(category, quarter, return_risk_rate
)
VALUES
("Category_01", "2019-Q1", "0.40"),
("Category_01", "2019-Q2", "0.45"),
("Category_01", "2019-Q3", "0.52"),
("Category_01", "2019-Q4", "0.67"),
("Category_02", "2019-Q1", "0.32"),
("Category_02", "2019-Q2", "0.47"),
("Category_02", "2019-Q3", "0.25"),
("Category_02", "2019-Q4", "0.32"),
("Category_03", "2019-Q1", "0.40"),
("Category_03", "2019-Q2", "0.52"),
("Category_03", "2019-Q3", "0.48"),
("Category_03", "2019-Q4", "0.61");
Expected Result:
category quarter sales return_risk_percentage return_risk_value
Category_01 2020-Q1 500 0.40 200
Category_01 2020-Q2 700 0.45 315
Category_01 2020-Q3 500 0.52 260
Category_01 2020-Q4 0 0.67 0
Category_02 2020-Q1 0 0.32 0
Category_02 2020-Q2 0 0.47 0
Category_02 2020-Q3 420 0.25 105
Category_02 2020-Q4 920 0.32 294.4
Category_03 2020-Q1 180 0.40 72
Category_03 2020-Q2 0 0.52 0
Category_03 2020-Q3 0 0.48 0
Category_03 2020-Q4 970 0.61 591.7
As you can see I have two tables called sales
and return_risk
.
In the table return_risk
an average percentage rate per quarter of the last year is calculated.
This average return rate should be applied to the sales
of the current year.
So far I came up with this query:
SELECT
s.category,
r.quarter,
r.return_risk_rate AS return_risk_%,
(s.category * r.return_risk_rate) AS return_risk_value
FROM sales s
JOIN return_risk r ON r.category = s.category
GROUP BY 1,2;
The issue is that I do not know how I can connect the date values
in column sales_date
with the corresponding quarter
in table return_risk
to apply the correct percentage rate for each category
and quarter
.
Do you have any idea how I can achieve this?
Upvotes: 1
Views: 34
Reputation: 147196
You should make note of the suggestions @Strawberry makes in terms of improving your data structure as it will simplify and make your query faster. In the interim, you can use this query with your existing data (but note I had to change the quarter values in return_risk
to 2020 to get any results). It LEFT JOIN
s return_risk
to sales
on the category
and quarter (which is manually constructed from the sales_date
field:
SELECT r.category,
r.quarter,
COALESCE(SUM(s.sales_volume), 0) AS sales,
r.return_risk_rate AS `return_risk_%`,
COALESCE(SUM(s.sales_volume) * r.return_risk_rate, 0) AS return_risk_value
FROM return_risk r
LEFT JOIN sales s ON r.category = s.category
AND r.quarter = CONCAT(YEAR(sales_date), '-Q', QUARTER(sales_date))
GROUP BY r.category, r.quarter, r.return_risk_rate
ORDER BY r.category, r.quarter
Output:
category quarter sales return_risk_% return_risk_value
Category_01 2020-Q1 500 0.40 200.00
Category_01 2020-Q2 700 0.45 315.00
Category_01 2020-Q3 500 0.52 260.00
Category_01 2020-Q4 0 0.67 0.00
Category_02 2020-Q1 0 0.32 0.00
Category_02 2020-Q2 0 0.47 0.00
Category_02 2020-Q3 420 0.25 105.00
Category_02 2020-Q4 920 0.32 294.40
Category_03 2020-Q1 180 0.40 72.00
Category_03 2020-Q2 0 0.52 0.00
Category_03 2020-Q3 0 0.48 0.00
Category_03 2020-Q4 970 0.61 591.70
Upvotes: 1
Reputation: 33945
Consider the following, which includes an amendment from my earlier solution, allowing use of an index...
DROP TABLE IF EXISTS sales;
CREATE TABLE sales (
id int auto_increment primary key,
category_id INT NOT NULL,
sales_date DATE NOT NULL,
sales_volume INT NOT NULL,
INDEX(category_id,sales_date)
);
INSERT INTO sales
(category_id, sales_date, sales_volume
)
VALUES
(1, "2020-01-03", 500),
(1, "2020-04-15", 700),
(1, "2020-08-27", 180),
(1, "2020-09-29", 320),
(2, "2020-07-17", 420),
(2, "2020-12-24", 350),
(2, "2020-12-08", 570),
(3, "2020-01-10", 180),
(3, "2020-10-20", 970);
DROP TABLE IF EXISTS return_risk;
CREATE TABLE return_risk (
category_id INT NOT NULL,
year INT NOT NULL,
quarter INT NOT NULL,
return_risk_rate DECIMAL(5,2),
PRIMARY KEY(category_id,year,quarter)
);
INSERT INTO return_risk
(category_id, year,quarter, return_risk_rate
)
VALUES
(1, 2019,1,0.40),
(1, 2019,2,0.45),
(1, 2019,3,0.52),
(1, 2019,4,0.67),
(2, 2019,1,0.32),
(2, 2019,2,0.47),
(2, 2019,3,0.25),
(2, 2019,4,0.32),
(3, 2019,1,0.40),
(3, 2019,2,0.52),
(3, 2019,3,0.48),
(3, 2019,4,0.61);
SELECT s.*
, r.return_risk_rate
, r.return_risk_rate * sales_volume expected_return
FROM sales s
JOIN return_risk r
ON r.category_id = s.category_id
AND s.sales_date >= CONCAT_WS('-','2020',LPAD((r.quarter*3)-2,2,'0'),'01')
AND s.sales_date < CONCAT_WS('-','2020',LPAD((r.quarter*3),2,'0'),'01')+INTERVAL 1 MONTH - INTERVAL 1 DAY;
+----+-------------+------------+--------------+------------------+-----------------+
| id | category_id | sales_date | sales_volume | return_risk_rate | expected_return |
+----+-------------+------------+--------------+------------------+-----------------+
| 1 | 1 | 2020-01-03 | 500 | 0.40 | 200.00 |
| 2 | 1 | 2020-04-15 | 700 | 0.45 | 315.00 |
| 3 | 1 | 2020-08-27 | 180 | 0.52 | 93.60 |
| 4 | 1 | 2020-09-29 | 320 | 0.52 | 166.40 |
| 5 | 2 | 2020-07-17 | 420 | 0.25 | 105.00 |
| 6 | 2 | 2020-12-24 | 350 | 0.32 | 112.00 |
| 7 | 2 | 2020-12-08 | 570 | 0.32 | 182.40 |
| 8 | 3 | 2020-01-10 | 180 | 0.40 | 72.00 |
| 9 | 3 | 2020-10-20 | 970 | 0.61 | 591.70 |
+----+-------------+------------+--------------+------------------+-----------------+
Upvotes: 1