解开子查询

时间:2014-09-17 21:45:30

标签: mysql sql subquery

我有一个相当复杂的查询返回一行,我想扩展它以返回多行,每个区域一行。现在,我可以使用以下查询一次获取一个区域的统计数据(在示例中,为“West”区域):

SELECT Count(id)       totalcustomers,
       Sum(ordertotal) totaldollars
FROM   (SELECT c.*
        FROM   customers c
               JOIN customeraddresses ca
                 ON c.id = ca.customerid
        WHERE  ca.state IN (SELECT state
                            FROM   stateregions
                            WHERE  region = "West")
        GROUP  BY c.id) t  

我想一次获得所有地区的汇总表:第一列应该有地区名称,然后其他列应该有摘要统计数据,就像他们已经做的那样。

正在运行的示例位于http://sqlfiddle.com/#!2/297e86/5

如果SQLFiddle出现问题,这里是数据结构:

CREATE TABLE customers
    (
     id INT, 
     ordertotal INT,
     PRIMARY KEY (id)
    );

INSERT INTO customers
(id, ordertotal)
VALUES
(1, 100),
(2, 250),
(3, 120);


CREATE TABLE customeraddresses (
  customerid INT,
  state char(2),
  PRIMARY KEY (customerid,state)
);

INSERT INTO customeraddresses
(customerid, state)
VALUES
(1, 'ca'),
(2, 'ny'),
(3, 'ny'),
(3, 'ca');

CREATE TABLE stateregions (
  region varchar(20),
  state char(2),
  PRIMARY KEY (region,state)
);

INSERT INTO stateregions
(region, state)
VALUES
('West', 'ca'),
('East', 'ny');

显然,此示例的结构和值已大大简化,因此请询问是否有任何不清楚的地方。谢谢!

3 个答案:

答案 0 :(得分:2)

您只需要JOINstateregions表,然后GROUP BY该地区:

  SELECT region, count(id) totalcustomers,sum(ordertotal) totaldollars
  FROM customers c 
    JOIN customeraddresses ca ON c.id = ca.customerid
    JOIN stateregions s on ca.state = s.state
  GROUP BY s.region

这将为每个区域返回一行:

REGION  TOTALCUSTOMERS  TOTALDOLLARS
East    2               370
West    2               220

代替潜在的重复项,distinct的子查询应该适合您:

SELECT region, COUNT(id), SUM(ordertotal)
FROM (
  SELECT DISTINCT c.id, c.ordertotal, s.region
  FROM customers c 
      JOIN customeraddresses ca ON c.id = ca.customerid
      JOIN stateregions s on ca.state = s.state
  ) t
GROUP BY region

导致:

REGION  TOTALCUSTOMERS  TOTALDOLLARS
All     3               470
East    2               370
West    2               220

答案 1 :(得分:0)

将每个子查询转换为内连接

SELECT Count(id)       totalcustomers,
       Sum(ordertotal) totaldollars
        FROM   customers c
               JOIN customeraddresses ca
                 ON c.id = ca.customerid
 inner join stateregions sr on sr.state = ca.state

其中sr.region =" WEST"

答案 2 :(得分:0)

您遇到问题,因为客户有多个地址。因此,它们可以在多个地区。以下方法为每个客户选择任意区域:

    SELECT car.region, count(id) as totalcustomers,
           sum(ordertotal) as totaldolalrs
    FROM customers c JOIN
         (select ca.customerid, max(region) as region
          from customeraddresses ca join
               stateregions sr
                on sr.state = ca.state
          group by ca.customerid
         ) car
         ON c.id = car.customerid
    GROUP BY car.region ;

更复杂的方法是将客户分配到他们所属的所有区域,然后按比例分配或重复计算。以下按比例分配:

    SELECT car.region, count(id) as totalcustomers,
           sum(ordertotal) as totaldolalrs
    FROM customers c JOIN
         (select ca.customerid, max(region) as region
          from customeraddresses ca join
               stateregions sr
                on sr.state = ca.state
         ) car

         ON c.id = car.customerid
    GROUP BY car.region ;

这些查询位于this SQL Fiddle。