Подсчет строк из подзапроса

13

Просто: я бы хотел посчитать количество строк в подзапросе. Обратите внимание, что статус зависит от того, находится хост в сети или нет.

Плохой код

SELECT COUNT(ip_address) FROM `ports` (
    SELECT DISTINCT ip_address FROM `ports` WHERE status IS TRUE
)

Разъяснения

Первый запрос, когда выполняется сам по себе, возвращает это:

SELECT DISTINCT ip_address FROM `ports` WHERE status IS TRUE
ip_address  
192.168.1.1
192.168.1.2
192.168.1.248
192.168.1.251
192.168.1.254

Второй запрос, запущенный сам по себе, возвращает это:

SELECT COUNT(ip_address) FROM `ports`
17

Вопрос

Я хотел бы знать, как посчитать этот список из 5 IP-адресов.

Я искал в Интернете возможные решения этой простой проблемы и просто расстраивался, поэтому подумал, что спросить экспертов.

rwcommand
источник

Ответы:

18

Чтобы ответить на ваш непосредственный вопрос, как считать строки подзапроса, синтаксис выглядит следующим образом:

SELECT COUNT(*) FROM (subquery) AS some_name;

Подзапрос должен следовать сразу за ключевым словом FROM. (В MySQL также является обязательным присваивать имя подзапросу такого типа (на самом деле это называется производной таблицей ), поэтому вы можете увидетьAS some_name следующее.) Как вы написали, MySQL интерпретирует ваш скрипт как два независимых запроса, поэтому вы получаете два набора результатов.

Итак, так как подзапрос в вашем случае

SELECT DISTINCT ip_address FROM `ports` WHERE status IS TRUE

полный запрос будет выглядеть так:

SELECT COUNT(*) FROM (
    SELECT DISTINCT ip_address FROM `ports` WHERE status IS TRUE
) AS derived;

Но, как предложил Жюльен , вы можете переписать свой запрос так:

SELECT COUNT(DISTINCT ip_address) FROM `ports`;

Таким образом, вам вообще не нужна подзапрос / производная таблица, потому что функция COUNT будет считать только различные вхождения ip_addressв portsтаблице.

Андрей М
источник
FY: прекрасно работал и в Postgres 10: SELECT COUNT(*) FROM (select * from bme_wk_umatch_ug where rdbname = 'xxx) as tocount; мне пришлось использовать оригинальную концепцию OP, потому что я собираюсь считать строки в подзапросе INTERSECT.
JL Peyret
6

Вы должны перейти DISTINCTк COUNT():

SELECT COUNT(DISTINCT ip_address) FROM `ports`;

Это возвращает, 5потому что он считает только разные значения и подзапрос больше не нужен.

Однако этот запрос возвращается, 17потому что в portsтаблице 17 строк :

SELECT COUNT(ip_address) FROM `ports`;

Посмотрите эту SQL Fiddle .

Пример данных с 17 строками и 5 разными IP-адресами:

CREATE TABLE ports (ip_address varchar(20));

INSERT INTO `ports`(ip_address) VALUES
  ('192.168.1.1')
  , ('192.168.1.1')
  , ('192.168.1.1')
  , ('192.168.1.2')
  , ('192.168.1.2')
  , ('192.168.1.2')
  , ('192.168.1.2')
  , ('192.168.1.248')
  , ('192.168.1.248')
  , ('192.168.1.248')
  , ('192.168.1.248')
  , ('192.168.1.251')
  , ('192.168.1.251')
  , ('192.168.1.251')
  , ('192.168.1.254')
  , ('192.168.1.254')
  , ('192.168.1.254');
Жюльен Вавассер
источник