Я пытаюсь создать, как мне кажется, сравнительно простой отчет для интернет-магазина, используя MySQL 5.1.45
Магазин может принимать оплату в нескольких валютах.
Я создал несколько примеров таблиц с данными и пытаюсь сгенерировать простой набор табличных результатов, сгруппированных по дате и валюте, чтобы я мог построить эти цифры.
Я хочу видеть каждую валюту, доступную на дату, с 0 в результате, если в тот день не было продаж в этой валюте.
Если я могу заставить это работать, я хочу сделать то же самое, но также сгруппированный по идентификатору продукта.
В приведенных мной выборочных данных есть только 3 валюты и 2 идентификатора продукта, но на практике их может быть любое количество.
Я могу правильно группировать по дате, но затем, когда я добавляю группировку по валюте, мой запрос не возвращает то, что я хочу.
Я основал свою работу на этой статье .
Мой отчетный запрос, сгруппированный только по дате:
SELECT calendar.datefield AS date,
IFNULL(SUM(orders.order_value),0) AS total_value
FROM orders
RIGHT JOIN calendar ON (DATE(orders.order_date) = calendar.datefield)
WHERE (calendar.datefield BETWEEN (SELECT MIN(DATE(order_date)) FROM orders) AND (SELECT MAX(DATE(order_date)) FROM orders))
GROUP BY date
Теперь сгруппированы по дате и валюте:
SELECT calendar.datefield AS date, orders.currency_id,
IFNULL(SUM(orders.order_value),0) AS total_value
FROM orders
RIGHT JOIN calendar ON (DATE(orders.order_date) = calendar.datefield)
WHERE (calendar.datefield BETWEEN (SELECT MIN(DATE(order_date)) FROM orders) AND (SELECT MAX(DATE(order_date)) FROM orders))
GROUP BY date, orders.currency_id
Получаемые результаты (сгруппированные по дате и валюте):
+------------+-------------+-------------+
| date | currency_id | total_value |
+------------+-------------+-------------+
| 2009-08-15 | 3 | 81.94 |
| 2009-08-15 | 45 | 25.00 |
| 2009-08-15 | 49 | 122.60 |
| 2009-08-16 | NULL | 0.00 |
| 2009-08-17 | 45 | 25.00 |
| 2009-08-17 | 49 | 122.60 |
| 2009-08-18 | 3 | 81.94 |
| 2009-08-18 | 49 | 245.20 |
+------------+-------------+-------------+
Результаты, которые я хочу :
+------------+-------------+-------------+
| date | currency_id | total_value |
+------------+-------------+-------------+
| 2009-08-15 | 3 | 81.94 |
| 2009-08-15 | 45 | 25.00 |
| 2009-08-15 | 49 | 122.60 |
| 2009-08-16 | 3 | 0.00 |
| 2009-08-16 | 45 | 0.00 |
| 2009-08-16 | 49 | 0.00 |
| 2009-08-17 | 3 | 0.00 |
| 2009-08-17 | 45 | 25.00 |
| 2009-08-17 | 49 | 122.60 |
| 2009-08-18 | 3 | 81.94 |
| 2009-08-18 | 45 | 0.00 |
| 2009-08-18 | 49 | 245.20 |
+------------+-------------+-------------+
Схема и данные, которые я использую в своих тестах:
CREATE TABLE orders
(
id INT PRIMARY KEY AUTO_INCREMENT,
order_date DATETIME,
order_id INT,
product_id INT,
currency_id INT,
order_value DECIMAL(9,2),
customer_id INT
);
INSERT INTO orders (order_date, order_id, product_id, currency_id, order_value, customer_id)
VALUES
('2009-08-15 10:20:20', '123', '1', '45', '12.50', '322'),
('2009-08-15 12:30:20', '124', '1', '49', '122.60', '400'),
('2009-08-15 13:41:20', '125', '1', '3', '40.97', '324'),
('2009-08-15 10:20:20', '126', '2', '45', '12.50', '345'),
('2009-08-15 13:41:20', '131', '2', '3', '40.97', '756'),
('2009-08-17 10:20:20', '3234', '1', '45', '12.50', '1322'),
('2009-08-17 10:20:20', '4642', '2', '45', '12.50', '1345'),
('2009-08-17 12:30:20', '23', '2', '49', '122.60', '3142'),
('2009-08-18 12:30:20', '2131', '1', '49', '122.60', '4700'),
('2009-08-18 13:41:20', '4568', '1', '3', '40.97', '3274'),
('2009-08-18 12:30:20', '956', '2', '49', '122.60', '3542'),
('2009-08-18 13:41:20', '443', '2', '3', '40.97', '7556');
CREATE TABLE currency
(
id INT PRIMARY KEY,
name VARCHAR(255)
);
INSERT INTO currency (id, name)
VALUES
(3, 'Euro'),
(45, 'US Dollar'),
(49, 'CA Dollar');
CREATE TABLE calendar (datefield DATE);
DELIMITER |
CREATE PROCEDURE fill_calendar(start_date DATE, end_date DATE)
BEGIN
DECLARE crt_date DATE;
SET crt_date=start_date;
WHILE crt_date < end_date DO
INSERT INTO calendar VALUES(crt_date);
SET crt_date = ADDDATE(crt_date, INTERVAL 1 DAY);
END WHILE;
END |
DELIMITER ;
CALL fill_calendar('2008-01-01', '2011-12-31');