2011-05-02 18 views
6

Definitivamente soy un novato con SQL, he estado rompiendo la cabeza para escribir una consulta compleja con la siguiente estructura de la tabla en PostgreSQL:consulta con subconsulta recuento, combinación interna y el grupo

CREATE TABLE reports 
(
    reportid character varying(20) NOT NULL, 
    userid integer NOT NULL, 
    reporttype character varying(40) NOT NULL, 
) 

CREATE TABLE users 
(
    userid serial NOT NULL, 
    username character varying(20) NOT NULL, 
) 

El objetivo de la consulta es obtener la cantidad de tipos de informes por usuario y mostrarla en una columna. Hay tres tipos diferentes de informes.

una simple consulta con el grupo por va a resolver el problema, pero mostrarlo en diferentes filas:

select count(*) as Amount, 
     u.username, 
     r.reporttype 
from reports r, 
    users u 
where r.userid=u.userid 
group by u.username,r.reporttype 
order by u.username 
+1

¿Qué salida esperas? – Ruben

+0

Hay solo tres tipos diferentes de informes: "tipo1" "tipo2" "tipo3" y la consulta debe mostrar en una fila el nombre de usuario, la cantidad de informes "tipo1", la cantidad de informes "tipo2" y la cantidad de " type3 "informes. Perdón por la confusión –

+1

En la consulta de su ejemplo, usted usa c.userid y c.reporttype, pero ¿de dónde viene esa c? No ha hecho ningún alias llamado c o una tabla llamada c. – Ruben

Respuesta

14
SELECT 
    username, 
    (
    SELECT 
    COUNT(*) 
    FROM reports 
    WHERE users.userid = reports.userid && reports.reporttype = 'Type1' 
) As Type1, 
    (
    SELECT 
    COUNT(*) 
    FROM reports 
    WHERE users.userid = reports.userid && reports.reporttype = 'Type2' 
) As Type2, 
    (
    SELECT 
    COUNT(*) 
    FROM reports 
    WHERE users.userid = reports.userid && reports.reporttype = 'Type3' 
) As Type3 
FROM 
    users 
WHERE 
    EXISTS(
    SELECT 
     NULL 
    FROM 
     reports 
    WHERE 
     users.userid = reports.userid 
) 
+0

Eso funcionó bastante bien, pero ¿hay alguna manera de ignorar a los usuarios con cero informes? –

+0

Ver respuesta actualizada – Magnus

+0

No necesita actualizar su pregunta, solo marque la respuesta correcta como la solución. – Magnus

0

Si usted está buscando los "tipos de informes amountof por usuario", se le esperaba a vea un número, ya sea 1, 2 o 3 (dado que hay tres tipos diferentes de informes) contra cada usuario. No esperará que el tipo de informe (simplemente se contará no se muestre), por lo que no necesita el tipo de informe en la consulta SELECT o GROUP BY.

En su lugar, use COUNT (DISTINCT r.reporttype) para contar la cantidad de tipos de reportes diferentes que cada usuario usa.

SELECT 
COUNT(DISTINCT r.reporttype) as Amount 
,u.username 
FROM users u 
INNER JOIN reports r 
ON r.userid=u.userid 
GROUP BY 
u.username 
ORDER BY u.username 
+0

Eso no era todo lo que estaba buscando. Solo hay tres tipos diferentes de informes: "tipo1" "tipo2" "tipo3" y la consulta debe mostrar en una fila el nombre de usuario, la cantidad de informes "tipo1", la cantidad de informes "tipo2" y la cantidad de "tipo3" " informes. Perdón por la confusion. –

5
SELECT 
    u.username, 
    COUNT(CASE r.reporttype WHEN 1 THEN 1 END) AS type1Qty, 
    COUNT(CASE r.reporttype WHEN 2 THEN 1 END) AS type2Qty, 
    COUNT(CASE r.reporttype WHEN 3 THEN 1 END) AS type3Qty 
FROM reports r 
    INNER JOIN users u ON r.userid = u.userid 
GROUP BY u.username 

Si dialecto SQL de su servidor requiere la rama más para estar presente en expresiones CASE, añadir ELSE NULL antes de cada END.

+0

He votado positivamente porque no soy fanático de la subconsulta. Gracias. –

Cuestiones relacionadas