2009-09-01 26 views
5

Necesito una consulta que devolverá una tabla donde cada columna es el recuento de valores distintos en las columnas de otra tabla.SQL: contar el número de valores distintos en cada columna

sé cómo contar los valores distintos en una sola columna:

select count(distinct columnA) from table1; 

supongo que solo pude hacer de esto una muy larga cláusula select:

select count(distinct columnA), count(distinct columnB), ... from table1; 

pero eso no es muy elegante y está codificado. Prefiero algo más flexible.

+1

Esta es la solución más elegante y simple ... ¿quiere decir "dado el nombre de una tabla, darme recuentos distintos para cada columna en esa tabla"? – gbn

+1

¿Qué base de datos está usando? –

+0

Posible duplicado: http://stackoverflow.com/questions/1330692/distinct-pair-of-values-sql –

Respuesta

0

Agradezco todas las respuestas. Creo que la solución que mejor funcione para mí en esta situación (contar el número de valores distintos en cada columna de una tabla de un programa externo que no tenga conocimiento de la tabla excepto su nombre) es la siguiente:

Ejecutar "describe table1" y extraiga los nombres de las columnas del resultado.

Recorra los nombres de las columnas y cree la consulta para contar los distintos valores en cada columna. La consulta se verá algo así como "select count (distinct columnA), count (distinct columnB), ... from table1".

1

Este código debe darle todas las columnas en 'tabla1' con el recuento de valores distintivos respectivos para cada uno como datos.

DECLARE @TableName VarChar (Max) = 'table1' 
DECLARE @SqlString VarChar (Max) 

set @SqlString = (
    SELECT DISTINCT 
    'SELECT ' + 
     RIGHT (ColumnList, LEN (ColumnList)-1) + 
     ' FROM ' + Table_Name 
    FROM INFORMATION_SCHEMA.COLUMNS COL1 
     CROSS AppLy (
     SELECT ', COUNT (DISTINCT [' + COLUMN_NAME + ']) AS ' + '''' + COLUMN_NAME + '''' 
      FROM INFORMATION_SCHEMA.COLUMNS COL2 
      WHERE COL1.TABLE_NAME = COL2.TABLE_NAME 
      FOR XML PATH ('') 
    ) TableColumns (ColumnList) 
    WHERE 
     1=1 AND 
     COL1.TABLE_NAME = @TableName 
) 

EXECUTE (@SqlString) 
1

y es codificada.

No es hardcoding para proporcionar una lista de campo para una instrucción sql. Es práctica común y aceptable.

+0

... Como está creando programáticamente el SQL, hasta donde llega (siempre que sus usuarios nunca proporcionen los valores que usted pone en él - bien en esta pregunta, usted tiene la lista de columnas en algún lugar). – ijw

+0

si iba a code-gen SQL, y si estaba en MSSqlServer, verificaría sysobjects y syscolumns. –

+0

Si desea escribir el código de una manera más portátil, debe seleccionar Information_Schema.Tables e Information_Schema.Columnas, en lugar de seleccionar de sysobjects y syscolumns – Kibbee

-3

DISTINCT es malo. Hacer COUNT/GROUP BY

+0

Califique esto con más información. ¿Cómo se usa el mal distinto cuando se lo hace para COUNT/GROUP BY? – Kibbee

+0

DISTINCT se comporta de forma errática con conjuntos de datos más grandes y de una plataforma a otra. Al menos en mi experiencia. Encuentro que los resultados de agrupación son más predecibles, especialmente si se trata de datos codificados de manera diferente, UTF, etc. –

+0

Tendré que analizar el uso del grupo por. – Ryan

0

Esto no será necesariamente posible para todos los campos de una tabla. Por ejemplo, no puede hacer una DISTINCT contra un ntext o campo de imagen de SQL Server a menos que los envíe a otros tipos de datos y pierda algo de precisión.

+0

Buen punto. No debería tener que preocuparme por esto. Los campos solo serán texto o números. – Ryan

3

probar esto (sintaxis SQL Server 2005):

DECLARE @YourTable table (col1 varchar(5) 
         ,col2 int 
         ,col3 datetime 
         ,col4 char(3) 
         ) 

insert into @YourTable values ('abcdf',123,'1/1/2009','aaa') 
insert into @YourTable values ('aaaaa',456,'1/2/2009','bbb') 
insert into @YourTable values ('bbbbb',789,'1/3/2009','aaa') 
insert into @YourTable values ('ccccc',789,'1/4/2009','bbb') 
insert into @YourTable values ('aaaaa',789,'1/5/2009','aaa') 
insert into @YourTable values ('abcdf',789,'1/6/2009','aaa') 


;with RankedYourTable AS 
(
SELECT 
    ROW_NUMBER() OVER(PARTITION by col1 order by col1) AS col1Rank 
     ,ROW_NUMBER() OVER(PARTITION by col2 order by col2) AS col2Rank 
     ,ROW_NUMBER() OVER(PARTITION by col3 order by col3) AS col3Rank 
     ,ROW_NUMBER() OVER(PARTITION by col4 order by col4) AS col4Rank 
    FROM @YourTable 
) 
SELECT 
    SUM(CASE WHEN  col1Rank=1 THEN 1 ELSE 0 END) AS col1DistinctCount 
     ,SUM(CASE WHEN col2Rank=1 THEN 1 ELSE 0 END) AS col2DistinctCount 
     ,SUM(CASE WHEN col3Rank=1 THEN 1 ELSE 0 END) AS col3DistinctCount 
     ,SUM(CASE WHEN col4Rank=1 THEN 1 ELSE 0 END) AS col4DistinctCount 
    FROM RankedYourTable 

SALIDA:

col1DistinctCount col2DistinctCount col3DistinctCount col4DistinctCount 
----------------- ----------------- ----------------- ----------------- 
4     3     6     2 

(1 row(s) affected) 
+0

+1: Conciso, elegante, descarado ... – gbn

Cuestiones relacionadas