MySQL - 获取多个分组行的摘要?

时间:2010-02-17 18:17:08

标签: sql mysql database

2个表:所有者&汽车

车主可以拥有很多车。汽车可以标记为useful_offroad,useful_onroad或两者。 cars表有可用的offroad和useful_onroad字段,可以设置为0或1(no或yes)

考虑以下问题:

SELECT *
FROM owners
LEFT JOIN cars on cars.owner_id = owners.id
GROUP BY owners.id
ORDER BY owners.last_name

我的目标是返回一份车主名单,以及每辆车是否拥有一辆公路或越野车,或两者兼而有之:

    Last Name    First Name    Has Offroad Car      Has Onroad Car
----------------------------------------------------------------------
    Smith        Todd          Yes                   No
    Smith        Tom           Yes                   Yes
    Test         Sue           No                    Yes
    Thumb        Joe           No                    No
    White        Al            Yes                   No

我如何查询?考虑使用ROLLUP,但是如果摘要不是附加行而是在已经分组的所有者行上的实际字段,则更愿意。

4 个答案:

答案 0 :(得分:2)

使用:

   SELECT DISTINCT
          o.lastname,
          o.firstname,
          CASE WHEN COALESCE(y.num_offroad, 0) > 0 THEN 'yes' ELSE 'no' END AS "Has Offroad Car"
          CASE WHEN COALESCE(x.num_onroad, 0) > 0 THEN 'yes' ELSE 'no' END AS "Has Onroad Car"
     FROM OWNERS o
LEFT JOIN (SELECT c.owner_id,
                  COUNT(*) AS num_onroad
             FROM CARS c
            WHERE c.usable_onroad = 1
         GROUP BY c.owner_id) x ON x.owner_id = o.id
LEFT JOIN (SELECT c.owner_id,
                  COUNT(*) AS num_offroad
             FROM CARS c
            WHERE c.usable_offroad = 1
         GROUP BY c.owner_id) y ON y.owner_id = o.id

答案 1 :(得分:0)

使用子查询对所有标志求和,然后检查是否> 1应该完成这项工作:

SELECT last_name, first_name,
       CASE WHEN usable_offroad_count > 0 THEN 'Yes' ELSE 'No' END has_offroad_car,
       CASE WHEN usable_onroad_count > 0 THEN 'Yes' ELSE 'No' END has_onroad_car
FROM (
    SELECT owners.last_name, owners.first_name,
           SUM( cars.usable_offroad ) usable_offroad_count,
           SUM( cars.usable_onroad ) usable_onroad_count
    FROM owners
    LEFT JOIN cars on cars.owner_id = owners.id
    GROUP BY owners.id
)
ORDER BY last_name

答案 2 :(得分:0)

SELECT * ,
if ( cars.usable offroad = 1 and  usable_onroad= 1 , 'Both' 
     , if( cars.usable offroad = 1 and  usable_onroad= 0  , 'Offroad' , 'Onroad')
   )  as Status
FROM owners
LEFT JOIN cars on cars.owner_id = owners.id
GROUP BY owners.id
ORDER BY owners.last_name

答案 3 :(得分:0)

试试这个:

SELECT
    T1.lastname,
    T1.firstname,
    T1.id in (SELECT owner_id FROM cars WHERE usable_offroad) AS `Has Offroad Car`,
    T1.id in (SELECT owner_id FROM cars WHERE usable_onroad) AS `Has Onroad Car`
FROM owners T1
ORDER BY T1.lastname, T1.firstname

结果:

'Smith', 'Todd', 1, 0
'Smith', 'Tom', 1, 1
'Test', 'Sue', 0, 1
'Thumb', 'Joe', 0, 0
'White', 'Al', 1, 0

这是我的测试数据:

CREATE TABLE owners (id INT NOT NULL, firstname NVARCHAR(100) NOT NULL, lastname NVARCHAR(100) NOT NULL);
INSERT INTO owners (id, firstname, lastname) VALUES
(1, 'Todd', 'Smith'),
(2, 'Tom', 'Smith'),
(3, 'Sue', 'Test'),
(4, 'Joe', 'Thumb'),
(5, 'Al', 'White');

CREATE TABLE cars (id INT NOT NULL, owner_id INT NOT NULL, usable_onroad INT NOT NULL, usable_offroad INT NOT NULL);
INSERT INTO cars (id, owner_id, usable_offroad, usable_onroad) VALUES
(1, 1, 1, 0),
(2, 2, 1, 0),
(3, 2, 0, 1),
(4, 3, 0, 1),
(5, 3, 0, 1),
(6, 5, 1, 0);