2009-09-01 3 views
5

Мне нужен запрос, который будет возвращать таблицу, в которой каждый столбец является счетчиком различных значений в столбцах другой таблицы.SQL: подсчет количества различных значений в каждом столбце

Я знаю, как посчитать различные значения в одном столбце:

select count(distinct columnA) from table1; 

Я полагаю, что я мог бы просто сделать это очень долго выберите пункт:

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

, но это не очень элегантный и жесткий. Я бы предпочел что-то более гибкое.

+1

Это изящное и простейшее решение ... вы имеете в виду «заданное имя таблицы, дайте мне разные подсчеты для каждого столбца в этой таблице»? – gbn

+1

Какая база данных вы используете? –

+0

Возможный дубликат: http://stackoverflow.com/questions/1330692/distinct-pair-of-values-sql –

ответ

0

Я ценю все ответы. Я думаю, что решение, которое наилучшим образом подходит для меня в этой ситуации (подсчет количества различных значений в каждом столбце таблицы из внешней программы, не знающей таблицу, кроме ее имени) выглядит следующим образом:

Запуск «описать таблицу1» и вывести имена столбцов из результата.

Пронумеруйте имена столбцов и создайте запрос для подсчета различных значений в каждом столбце. Запрос будет выглядеть примерно так: «select count (отдельный столбец A), count (отдельный столбец B), ... из таблицы1».

1

Этот код должен предоставить вам все столбцы в таблице 1 с соответствующим отдельным значением для каждого в качестве данных.

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

и это жёстко.

Это не hardcoding, чтобы предоставить список полей для оператора sql. Это обычная и приемлемая практика.

+0

... Как программно создавая SQL, насколько это возможно (предоставляя вашим пользователям никогда не поставлять значения, которые вы вставляете в него - в этом вопросе отлично, у вас есть список столбцов где-нибудь). – ijw

+0

если бы я собирался кодировать некоторый SQL, и если бы я был на MSSqlServer, я бы проверял sysobjects и syscolumns. –

+0

Если вы хотите написать код более переносимым способом, вы должны выбрать из Information_Schema.Tables и Information_Schema.Столбцы, а не выбор из sysobjects и syscolumns – Kibbee

-3

DISTINCT is evil. Do COUNT/GROUP BY

+0

Просьба получить более подробную информацию. Как используется явное зло, когда вы компилируете COUNT/GROUP BY? – Kibbee

+0

DISTINCT ведет себя беспорядочно с большими наборами данных и с платформы на платформу. По крайней мере, по моему опыту. Я считаю, что результаты группировки более предсказуемы, особенно если вы имеете дело с по-разному закодированными данными, UTF и т. Д. –

+0

Мне нужно будет изучить группу. – Ryan

0

Это не обязательно будет возможно для каждого поля в таблице. Например, вы не можете использовать DISTINCT для поля ntext или изображения SQL Server, если вы не передадите их другим типам данных и не потеряете некоторую точность.

+0

Хорошая точка. Я не должен беспокоиться об этом. Поля будут только текстом или цифрами. – Ryan

3

попробовать это (SQL синтаксис сервера 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 

ВЫВОД:

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

(1 row(s) affected) 
+0

+1: краткий, элегантный, нахальный ... – gbn

Смежные вопросы