2010-07-20 72 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