简体   繁体   中英

mysql: union re-use subquery

There is a table:

ID        City      

1          Toronto
2          Toronto
3          Toronto
4          Toronto
5          NY
6          NY

How to get the following table:

City    Total

NULL    6
Toronto 4
NY      2

I plan to use union :

(select city, count(*) as total from tbl group by city)
union
(select null, count(*) as total from tbl)

Is it possible to use something like to reuse the subquery:

(select city, count(*) as total from tbl group by city) tmp
union
(select null, count(*) as tmp from tbl)

Or sql already optimizes

(select city, count(*) as total from tbl group by city)
union
(select null, count(*) as total from tbl)

?

In at least MySQL 5.5 and newer, you can use the WITH ROLLUP modifier to get a total sum of the grouped elements without an extra query;

SELECT city, COUNT(*) AS total FROM tbl GROUP BY city WITH ROLLUP

city      total
---------------
NY        2
Toronto   4
(null)    6

An SQLfiddle to test with .

You can't reuse the the query but you could use a view for reuse the code

  create view  my_view as 
  select city, count(*) as total 
  from tbl group by city

once created the view you could

  select  city, total 
  from my_view 
  union  
  select  null, sum(total)
  from my_view 

1) Take aliases are only visible to join members and subquery. Not to union members.

2) The query as you wrote it makes little sense: aliasing tmp to a table then a scalar?

To achieve what you want to achieve, you can try using CTEs:

WITH tmp AS (SELECT city, COUNT(*) AS cnt GROUP BY city) 
SELECT * FROM tmp UNION SELECT null, SUM(cnt) FROM tmp

I don't know what the performance difference would be. If you have an index on city , I doubt you will see a difference.

You use WITH ROLLUP in a subquery and then arrange the ordering in the outer query to put the rollup record on top:

SELECT *
FROM (SELECT city, COUNT(*) AS total FROM mytable GROUP BY city WITH ROLLUP) x 
ORDER BY
    CASE WHEN city IS NULL THEN 0 ELSE 1 END,
    city

If you are planning to order the results by descending total, that's even simpler:

SELECT *
FROM (SELECT city, COUNT(*) AS total FROM mytable GROUP BY city WITH ROLLUP) x 
ORDER BY total DESC

Demo on DB Fiddlde :

| city    | total |
| ------- | ----- |
|         | 6     |
| Toronto | 4     |
| NY      | 2     |

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM