2009-09-01 16 views
5

Ho bisogno di una query che restituirà una tabella in cui ogni colonna è il conteggio di valori distinti nelle colonne di un'altra tabella.SQL: numero di conteggi di valori distinti in ogni colonna

so come contare i valori distinti in una colonna:

select count(distinct columnA) from table1; 

Suppongo che ho potuto solo fare questa una clausola molto lungo select:

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

ma che non è molto elegante ed è hardcoded. Preferirei qualcosa di più flessibile.

+1

Questa è la soluzione elegante e più semplice ... intendi "dato un nome di tabella, darmi distinti conteggi per ogni colonna in quella tabella"? – gbn

+1

Quale database stai usando? –

+0

Eventuale duplicato: http://stackoverflow.com/questions/1330692/distinct-pair-of-values-sql –

risposta

0

Apprezzo tutte le risposte. Penso che la soluzione che funzionerà meglio per me in questa situazione (contando il numero di valori distinti in ogni colonna di una tabella da un programma esterno che non ha conoscenza della tabella tranne il suo nome) è la seguente:

Esegui "Descrivi table1" e tira fuori i nomi delle colonne dal risultato.

Passare attraverso i nomi delle colonne e creare la query per contare i valori distinti in ciascuna colonna. La query sarà simile a "select count (distinct columnA), count (distinct columnB), ... from table1".

1

Questo codice dovrebbe fornire tutte le colonne in "tabella1" con il rispettivo conteggio dei valori distinti per ciascuno come dati.

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

ed è hardcoded.

Non è hardcoding fornire un elenco di campi per un'istruzione sql. È una pratica comune e accettabile.

+0

... Come sta creando a livello di codice l'SQL, per quanto possibile (a condizione che i tuoi utenti non forniscano mai i valori che hai inserito - bene in questa domanda, hai l'elenco delle colonne da qualche parte). – ijw

+0

se dovessi scrivere qualche codice in SQL, e se fossi su MSSqlServer, controllerei sysobjects e syscolumns. –

+0

Se si desidera scrivere il codice in un modo più portatile, è necessario selezionare Information_Schema.Tables e Information_Schema.Colonne, anziché selezionare da sysobjects e syscolumns – Kibbee

-3

DISTINCT è malvagio. Effettuare COUNT/GROUP BY

+0

Si prega di qualificare questo con ulteriori informazioni. In che modo utilizzare il male distinto quando si esegue COUNT/GROUP BY? – Kibbee

+0

DISTINCT si comporta in modo errato con set di dati più grandi e da piattaforma a piattaforma. Almeno nella mia esperienza. Trovo che i risultati di raggruppamento siano più prevedibili, in particolare se gestisci dati codificati in modo diverso, UTF, ecc. –

+0

Dovrò esaminare l'utilizzo di group by. – Ryan

0

Ciò non sarà necessariamente possibile per ogni campo di una tabella. Ad esempio, non è possibile eseguire un DISTINCT su un ntext o un campo immagine di SQL Server a meno che non li si lanci su altri tipi di dati e si perda con precisione.

+0

Buon punto. Non dovrei preoccuparmi di questo. I campi saranno solo testo o numeri. – Ryan

3

provare questo (sintassi 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 

USCITA:

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

(1 row(s) affected) 
+0

+1: conciso, elegante, sfacciato ... – gbn

Problemi correlati