2010-07-20 3 views
7

У меня есть три таблицы со следующей структурой и данные:SQL-запросы, чтобы присоединиться три таблицы

CREATE TABLE customer (
    customer_id mediumint(8) unsigned NOT NULL auto_increment, 
    name varchar(50) NOT NULL, 
    PRIMARY KEY (customer_id) 
); 

INSERT INTO customer VALUES (1, 'Dagmar'); 
INSERT INTO customer VALUES (2, 'Dietmar'); 
INSERT INTO customer VALUES (3, 'Sabine'); 

CREATE TABLE sales_cars (
    sale_id mediumint(8) unsigned NOT NULL auto_increment, 
    customer_id mediumint(8) unsigned NOT NULL, 
    sale_amount decimal(10,2) NOT NULL, 
    PRIMARY KEY (sale_id) 
); 

INSERT INTO sales_cars VALUES (1, 3, 14.40); 
INSERT INTO sales_cars VALUES (2, 1, 28.30); 
INSERT INTO sales_cars VALUES (3, 2, 34.40); 
INSERT INTO sales_cars VALUES (4, 2, 25.60); 

CREATE TABLE sales_parts (
    sale_id mediumint(8) unsigned NOT NULL auto_increment, 
    customer_id mediumint(8) unsigned NOT NULL, 
    sale_amount decimal(10,2) NOT NULL, 
    PRIMARY KEY (sale_id) 
); 

INSERT INTO sales_parts VALUES (1, 2, 68.20); 
INSERT INTO sales_parts VALUES (2, 3, 21.30); 
INSERT INTO sales_parts VALUES (3, 3, 54.40); 
INSERT INTO sales_parts VALUES (4, 1, 35.70); 

sales_car и sales_parts владения продаж, сделанные клиентами. Идея состоит в том, чтобы написать запрос, который суммирует «sale_amount» обоих автомобилей и частей для конкретного клиента и группирует результат по id.

Есть ли у кого-то предложение, как я могу решить эту проблему?

+2

+1 для включения структуры с информацией об образце в SQL :) –

ответ

2

Что-то вроде этого будет то, что вы после ...

SELECT *, 
     (SELECT SUM(sale_amount) 
      FROM sales_cars 
      WHERE sales_cars.customer_id = customer.customer_id) AS car_sales, 
     (SELECT SUM(sale_amount) 
      FROM sales_parts 
      WHERE sales_parts.customer_id = customer.customer_id) AS part_sales 
    FROM customer; 
+0

ваше решение дает мне sale_amount для каждого клиента в отдельных таблицах. Идея заключалась в том, чтобы получить одно значение для sale_amount, т. Е. Добавить значения из обеих таблиц. Я не подтвердил решение 1 выше, но мне кажется, что я требую. Спасибо за ваше внимание – user224645

3

Вы можете попробовать что-то вроде следующего:

SELECT c.customer_id, 
     tot_cars.total + tot_parts.total AS total_sales 
FROM customer c 
JOIN (
      SELECT customer_id, SUM(sale_amount) total 
      FROM  sales_cars 
      GROUP BY customer_id 
     ) tot_cars ON (tot_cars.customer_id = c.customer_id) 
JOIN (
      SELECT customer_id, SUM(sale_amount) total 
      FROM  sales_parts 
      GROUP BY customer_id 
     ) tot_parts ON (tot_parts.customer_id = c.customer_id); 

Результат:

+-------------+-------------+ 
| customer_id | total_sales | 
+-------------+-------------+ 
|   1 |  64.00 | 
|   2 |  128.20 | 
|   3 |  90.10 | 
+-------------+-------------+ 
3 rows in set (0.03 sec) 

ОБНОВЛЕНИЕ: Далее в комментарии ниже:

Давайте начнем с sale_date поля:

CREATE TABLE sales_cars (
    sale_id mediumint(8) unsigned NOT NULL auto_increment, 
    customer_id mediumint(8) unsigned NOT NULL, 
    sale_amount decimal(10,2) NOT NULL, 
    sale_date datetime NOT NULL, 
    PRIMARY KEY (sale_id) 
); 

INSERT INTO sales_cars VALUES (1, 3, 14.40, '2010-07-01 12:00:00'); 
INSERT INTO sales_cars VALUES (2, 1, 28.30, '2010-07-05 12:00:00'); 
INSERT INTO sales_cars VALUES (3, 2, 34.40, '2010-07-10 12:00:00'); 
INSERT INTO sales_cars VALUES (4, 2, 25.60, '2010-07-20 12:00:00'); 

Чтобы получить дату последней продажи каждого клиента, вы можете присоединиться к запросу, описанный ранее с другой производной таблицей, как показано ниже :

SELECT c.customer_id, 
     tot_cars.total + tot_parts.total AS total_sales, 
     latest_sales.date AS latest_sale 
FROM customer c 
JOIN (
      SELECT customer_id, SUM(sale_amount) total 
      FROM  sales_cars 
      GROUP BY customer_id 
     ) tot_cars ON (tot_cars.customer_id = c.customer_id) 
JOIN (
      SELECT customer_id, SUM(sale_amount) total 
      FROM  sales_parts 
      GROUP BY customer_id 
     ) tot_parts ON (tot_parts.customer_id = c.customer_id) 
JOIN (
      SELECT customer_id, MAX(sale_date) date 
      FROM  sales_cars 
      GROUP BY customer_id 
     ) latest_sales ON (latest_sales.customer_id = c.customer_id); 

Результат:

+-------------+-------------+---------------------+ 
| customer_id | total_sales | latest_sale   | 
+-------------+-------------+---------------------+ 
|   1 |  64.00 | 2010-07-05 12:00:00 | 
|   2 |  128.20 | 2010-07-20 12:00:00 | 
|   3 |  90.10 | 2010-07-01 12:00:00 | 
+-------------+-------------+---------------------+ 
3 rows in set (0.07 sec) 

Вы видите шаблон? Существуют другие подходы к решению одной и той же проблемы, но объединение с производными таблицами - очень простой и простой метод.

Тогда об изменениях в customer таблице, я полагаю, вы имеете в виду что-то вроде этого:

CREATE TABLE customer (
    customer_id mediumint(8) unsigned NOT NULL auto_increment, 
    first_name varchar(50) NOT NULL, 
    last_name varchar(50) NOT NULL, 
    gender char(1) NOT NULL, 
    PRIMARY KEY (customer_id) 
); 

INSERT INTO customer VALUES (1, 'Joe', 'Doe', 'M'); 
INSERT INTO customer VALUES (2, 'Jane', 'Smith', 'F'); 
INSERT INTO customer VALUES (3, 'Peter', 'Brown', 'M'); 

конкатенировать строковые поля в MySQL, вы можете просто использовать CONCAT() функцию:

SELECT CONCAT(c.first_name, ' ', c.last_name) as full_name 
FROM customer c; 

Возврат:

+-------------+ 
| full_name | 
+-------------+ 
| Jane Smith | 
| Peter Brown | 
| Joe Doe  | 
+-------------+ 
3 rows in set (0.01 sec) 

Для применения 'Г-н' или 'госпожа' условно, вы можете использовать CASE заявление:

SELECT (CASE c.gender WHEN 'M' THEN 'Mr' WHEN 'F' THEN 'Ms' END) salutaiton, 
     CONCAT(c.first_name, ' ', c.last_name) as full_name 
FROM customer c; 

возвращений:

+------------+-------------+ 
| salutaiton | full_name | 
+------------+-------------+ 
| Ms   | Jane Smith | 
| Mr   | Peter Brown | 
| Mr   | Joe Doe  | 
+------------+-------------+ 
3 rows in set (0.01 sec) 

Вы также можете соединить два поля вместе:

SELECT CONCAT((CASE c.gender WHEN 'M' THEN 'Mr' WHEN 'F' THEN 'Ms' END), ' ', 
       c.first_name, ' ', c.last_name) as full_name 
FROM customer c; 

Возвращает :

+----------------+ 
| full_name  | 
+----------------+ 
| Ms Jane Smith | 
| Mr Peter Brown | 
| Mr Joe Doe  | 
+----------------+ 
3 rows in set (0.00 sec) 

Наконец, мы можем приложить это к нашему основному запросу, следующим образом:

SELECT c.customer_id, 
     CONCAT((CASE c.gender WHEN 'M' THEN 'Mr' WHEN 'F' THEN 'Ms' END), ' ', 
        c.first_name, ' ', c.last_name) as full_name, 
     tot_cars.total + tot_parts.total AS total_sales, 
     latest_sales.date AS latest_sale 
FROM customer c 
JOIN (
      SELECT customer_id, SUM(sale_amount) total 
      FROM  sales_cars 
      GROUP BY customer_id 
     ) tot_cars ON (tot_cars.customer_id = c.customer_id) 
JOIN (
      SELECT customer_id, SUM(sale_amount) total 
      FROM  sales_parts 
      GROUP BY customer_id 
     ) tot_parts ON (tot_parts.customer_id = c.customer_id) 
JOIN (
      SELECT customer_id, MAX(sale_date) date 
      FROM  sales_cars 
      GROUP BY customer_id 
     ) latest_sales ON (latest_sales.customer_id = c.customer_id); 

Возвраты:

+-------------+----------------+-------------+---------------------+ 
| customer_id | full_name  | total_sales | latest_sale   | 
+-------------+----------------+-------------+---------------------+ 
|   1 | Mr Joe Doe  |  64.00 | 2010-07-05 12:00:00 | 
|   2 | Ms Jane Smith |  128.20 | 2010-07-20 12:00:00 | 
|   3 | Mr Peter Brown |  90.10 | 2010-07-01 12:00:00 | 
+-------------+----------------+-------------+---------------------+ 
3 rows in set (0.02 sec) 
+0

Это именно то, что я хотел поблагодарить. Представьте, что теперь я удаляю столбец имен в таблице клиентов, чтобы добавить 3 новых столбца: «пол», «фамилия» и «первое имя». Идея состоит в том, чтобы показать total_sales с именем клиента в форме, например, г-н Dietmar Peter. Таким образом, усложнение здесь превращает пол в любого г-на миссис и сочетает первое и последнее имя. Во-вторых, если в sales_cars и sales_parts был добавлен новый столбец «sale_date», как вы могли бы вывести дату последней продажи вдоль стороны total_sales в новом столбце. Спасибо alot – user224645

+0

@vibanty: Проверьте обновленный ответ :) –

1
select customer.customer_id,(totalcar + totalparts) as total from customer 
inner join 
(select customer_id ,sum(sale_amount) as totalcar 
     from sales_cars group by customer_id) d 
on customer_id = d.customer_id 
inner join 
(select customer_id , sum(sale_amount) as totalparts 
     from sales_parts group by customer_id) d1 

on customer_id = d1. customer_id 
+0

Я проверил ваш результат и отметим следующее: 1- customer_id после «on» части объединения - это ambiguos, так как customer_id появляется на всех трех таблицах 2 - ваше решение выпустит отдельную часть для продажи автомобилей и запчастей каждого клиента. Требование состоит в том, чтобы суммировать сумму. Посмотрите первое решение, которое я подтвердил как правильный. Спасибо за ваш вклад – user224645

+0

см. Ответ обновлено сейчас –

0

я не думаю, что агрегированные подзапросов хорошая идея

select customer_id, sum(sale_amount) from (
select customer.customer_id, sale_amount from customer 
join sales_cars on sales_cars.customer_id = customer.customer_id 
union all 
select customer.customer_id, sale_amount from customer 
join sales_parts on sales_parts.customer_id = customer.customer_id 
) totals group by customer_id 
+3

Всякий раз, когда вы ловите себя, напишите 'UNION', проверьте, будет ли работать UNION ALL', так как дельта производительности ~ O (n log n). На самом деле здесь 'UNION' без' ALL' является ошибкой (хотя обычно у вас не будет части, которая стоит столько же, сколько целая машина, проданная одному клиенту). – Unreason

+0

Предоставлено здесь либо синтетический ключ, либо объединение. –

+0

Большое спасибо за ваш вклад.Представьте, что теперь я удаляю столбец имен в таблице клиентов, чтобы добавить 3 новых столбца: «пол», «фамилия» и «первое имя». Идея состоит в том, чтобы показать total_sales с именем клиента в форме, например, г-н Dietmar Peter. Таким образом, усложнение здесь превращает пол в любого г-на миссис и сочетает первое и последнее имя. Во-вторых, если в sales_cars и sales_parts был добавлен новый столбец «sale_date», как вы могли бы вывести дату последней продажи вдоль стороны total_sales в новом столбце. Большое спасибо – user224645

Смежные вопросы