2009-09-01 48 views
5

我需要一個查詢來返回一個表,其中每列是另一個表的列中不同值的計數。SQL:計算每列中不同值的數量

我知道如何計算一列內不同的值:我想,我可能只是使這是一個很長的SELECT子句

select count(distinct columnA) from table1; 

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

,但不是很優雅和硬編碼。我更喜歡更靈活的東西。

+1

這是一個優雅和最簡單的解決方案......你的意思是「給定一個表名,給出該表中每列的不同計數」? – gbn 2009-09-01 17:09:45

+1

您正在使用哪個數據庫? – 2009-09-01 17:11:03

+0

可能的重複:http://stackoverflow.com/questions/1330692/distinct-pair-of-values-sql – 2009-09-01 17:12:48

回答

0

我感謝所有的答覆。我認爲在這種情況下最適合我的解決方案(從不知道表名的外部程序中計算表中每列的不同值的數量)如下:

運行「描述table1」並從結果中提取列名稱。

循環遍歷列名並創建查詢來計算每列中的不同值。該查詢看起來像「select count(distinct columnA),count(distinct columnB)... from table1」。

1

此代碼應該爲'table1'中的所有列提供每個列的相應不同值作爲數據。

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

,它的硬編碼。

提供sql語句的字段列表並不是硬編碼。這是常見和可接受的做法。

+0

...正如程序化地創建SQL,只要它(提供您的用戶永遠不會提供您輸入的值 - 在這個問題中很好,你有列列表的地方)。 – ijw 2009-09-01 17:18:58

+0

如果我打算編寫一些SQL代碼,並且如果我在MSSqlServer上,我會檢查sysobjects和syscolumns。 – 2009-09-01 17:23:45

+0

如果您想以更便攜的方式編寫代碼,您應該從Information_Schema.Tables和Information_Schema中進行選擇。列,而不是從sysobjects和syscolumns中選擇 – Kibbee 2009-09-01 17:51:05

-3

DISTINCT是邪惡的。做COUNT/GROUP BY

+0

請通過更多信息對此進行限定。編寫COUNT/GROUP BY時如何使用distinct evil? – Kibbee 2009-09-01 17:49:45

+0

DISTINCT對於較大的數據集以及從平臺到平臺的行爲不正常。至少在我的經驗。我發現分組結果更具可預測性,特別是如果您處理不同編碼的數據,UTF等。 – 2009-09-01 17:55:24

+0

我將不得不使用group by。 – Ryan 2009-09-01 18:29:59

0

這對錶中的每個字段都不一定是可能的。例如,除非將其轉換爲其他數據類型並失去一些精度,否則無法對SQL Server ntext或image字段執行DISTINCT。

+0

好點。我不應該擔心這一點。這些字段只能是文本或數字。 – Ryan 2009-09-01 18:29:21

3

試試這個(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 

OUTPUT:

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

(1 row(s) affected) 
+0

+1:簡潔,優雅,厚臉皮... – gbn 2009-09-01 18:35:24