mysql: объединение повторно использовать подзапрос - PullRequest
0 голосов
/ 29 сентября 2019

Есть таблица:

ID        City      

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

Как получить следующую таблицу:

City    Total

NULL    6
Toronto 4
NY      2

Я планирую использовать union:

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

Можно ли использовать что-то вроде повторного использования подзапроса:

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

Или sql уже оптимизирует

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

?

Ответы [ 4 ]

3 голосов
/ 29 сентября 2019

По крайней мере, в MySQL 5.5 и новее можно использовать модификатор WITH ROLLUP, чтобы получить общую сумму сгруппированных элементов без дополнительного запроса;

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

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

SQLfiddle для тестирования с .

0 голосов
/ 29 сентября 2019

Вы используете WITH ROLLUP в подзапросе, а затем упорядочиваете порядок во внешнем запросе, чтобы поместить сводную запись сверху:

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

Если вы планируете упорядочить результаты по убыванию итогов, этоеще проще:

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

Демонстрация на DB Fiddlde :

| city    | total |
| ------- | ----- |
|         | 6     |
| Toronto | 4     |
| NY      | 2     |
0 голосов
/ 29 сентября 2019

1) Взять псевдонимы видны только для присоединения участников и подзапросов. Не объединять членов.

2) В написанном вами запросе нет никакого смысла: совмещать tmp с таблицей, а затем с скаляром?

Чтобы достичь того, чего вы хотите достичь, вы можете попробовать использоватьCTE:

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

Я не знаю, какая разница в производительности. Если у вас есть индекс на city, я сомневаюсь, что вы увидите разницу.

0 голосов
/ 29 сентября 2019

Вы не можете повторно использовать запрос, но вы можете использовать представление для повторного использования кода

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

после создания представления вы можете

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