2010-07-20 101 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_carsales_parts保持銷售。這個想法是編寫一個查詢,將特定客戶的汽車和零件的「sale_amount」相加,並將結果按ID進行分組。

有人有一個建議我怎麼能解決這個問題?

+2

+1在SQL中包含具有示例信息的結構:) – 2010-07-20 12:12:02

回答

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 2010-07-22 07:59:56

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) 

UPDATE:繼下面的評論:

讓我們先從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個新列:「gender」,「lastname」和「firstname」。我們的想法是,以Dietmar Peter先生的形式顯示客戶的姓名,例如total_sales。所以這裏的複雜性就是把性別變成夫人先生,把姓氏和名字結合起來。其次,如果在sales_cars和sales_parts中添加了新的「sale_date」列,那麼您將如何輸出最近一次銷售的日期,以及total_sales在新列中的說法。非常感謝 – user224645 2010-07-22 08:26:48

+0

@vibanty:檢查更新後的答案:) – 2010-07-22 10:07:50

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-在加入的「on」部分之後的customer_id是ambiguos,因爲customer_id出現在所有三個表中 2 - 您的解決方案將爲每位客戶的汽車和零部件銷售單獨發行一些。要求是加總。看到我已經驗證的第一個解決方案是正確的。 感謝您的貢獻 – user224645 2010-07-22 08:40:19

+0

查看現在更新的答案 – 2010-07-22 08:51:02

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)。實際上,沒有'ALL'的'UNION'是一個錯誤(儘管通常你不會有一部分的成本與賣給同一客戶的整車相當)。 – Unreason 2010-07-20 13:15:17

+0

授予,無論是合成密鑰或工會都在這裏失蹤。 – 2010-07-20 13:45:07

+0

非常感謝您的貢獻。想象一下,我現在刪除客戶表中的名稱列以添加3個新列:「gender」,「lastname」和「firstname」。我們的想法是,以Dietmar Peter先生的形式顯示客戶的姓名,例如total_sales。所以這裏的複雜性就是把性別變成夫人先生,把姓氏和名字結合起來。其次,如果在sales_cars和sales_parts中添加了新的「sale_date」列,那麼您將如何輸出最近一次銷售的日期,以及total_sales在新列中的說法。非常感謝 – user224645 2010-07-22 08:53:01