Contando linhas de uma subconsulta

13

Simples: gostaria de contar o número de linhas da subconsulta. Observe que o status é se o host está online ou não.

Código incorreto

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

Explicado

A primeira consulta, quando executada sozinha, retorna isso:

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

A segunda consulta executada por si só retorna isso:

SELECT COUNT(ip_address) FROM `ports`
17

Questão

Gostaria de saber como contar essa lista de 5 endereços IP.

Estive pesquisando on-line possíveis soluções para esse problema simples e estou ficando frustrado, por isso pensei em perguntar aos especialistas.

rwcommand
fonte

Respostas:

18

Para responder sua pergunta imediata, como contar as linhas de uma subconsulta, a sintaxe é a seguinte:

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

A subconsulta deve seguir imediatamente a palavra-chave FROM. (No MySQL, também é obrigatório atribuir um nome a uma subconsulta desse tipo (na verdade, é chamada de tabela derivada ), e é por isso que você pode ver o AS some_nameseguinte.) Da maneira como você o escreveu, o MySQL interpreta seu script como duas consultas independentes, é por isso que você está recebendo dois conjuntos de resultados.

Portanto, como a subconsulta no seu caso é

SELECT DISTINCT ip_address FROM `ports` WHERE status IS TRUE

a consulta completa ficaria assim:

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

Mas, como Julien sugeriu , você pode reescrever sua consulta assim:

SELECT COUNT(DISTINCT ip_address) FROM `ports`;

Dessa forma, você não precisa de uma subconsulta / tabela derivada, porque a função COUNT contará apenas ocorrências distintas ip_addressna portstabela.

Andriy M
fonte
FY: também funcionou bem no Postgres 10: SELECT COUNT(*) FROM (select * from bme_wk_umatch_ug where rdbname = 'xxx) as tocount; eu tive que usar o conceito original dos OPs porque vou contar as linhas em uma subconsulta INTERSECT.
JL Peyret
6

Você deve mover o DISTINCTpara COUNT():

SELECT COUNT(DISTINCT ip_address) FROM `ports`;

Isso retorna 5porque conta apenas valores distintos e a subconsulta não é mais necessária.

No entanto, essa consulta retorna 17porque há 17 linhas na portstabela:

SELECT COUNT(ip_address) FROM `ports`;

Veja este SQL Fiddle .

Amostra de dados com 17 linhas e 5 IPs distintos:

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');
Julien Vavasseur
fonte