Michi
Michi

Reputation: 5471

Multiply daily-based values from one table with quarter-based values from another table

DB-Fiddle

/* 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

Answers (2)

Nick
Nick

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 JOINs 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

Demo on dbfiddle

Upvotes: 1

Strawberry
Strawberry

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

Related Questions