2015-05-14 5 views
3

Я пытаюсь написать запрос, который будет производить очень маленький образец данных из каждого столбца таблицы, в котором образец составлен из верхней 3 наиболее распространенные значения. Эта конкретная проблема является частью более крупной задачи, которая заключается в написании сценариев, которые могут характеризовать базу данных и ее таблицы, целостность данных, а также быстро просматривать общие значения в таблице на основе столбцов. Подумайте об этом как о автоматизированном «анализе» таблицы.Получить три самых распространенных значения из каждого столбца таблицы

В одной колонке я делаю это, просто вычисляя частоту значений, а затем сортируя по частоте. Если бы у меня был столбец с названием «цвет», и все цвета были в нем, и так получилось, что цвет «синий» был в большинстве строк, тогда первое наиболее часто встречающееся значение было бы «синим». В SQL, который легко вычислить.

Однако я не уверен, как бы это сделать с несколькими столбцами.

В настоящее время, когда я делаю расчет по всем столбцам таблицы, я выполняю следующий тип запроса:

USE database; 

DECLARE @t nvarchar(max) 
SET @t = N'SELECT ' 

SELECT @t = @t + 'count(DISTINCT CAST(' + c.name + ' as varchar(max))) "' + c.name + '",' 
FROM sys.columns c 
WHERE c.object_id = object_id('table'); 

SET @t = SUBSTRING(@t, 1, LEN(@t) - 1) + ' FROM table;' 

EXEC sp_executesql @t 

Однако его не совсем понятно, как я хотел бы сделать это здесь.

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

Но проблема получения тройки самые частые значения за столбец заставили меня полностью застопорить.

В идеале, я хотел бы закончить с чем-то вроде этого:

Col1  Col2    Col3  Col4  Col5 
--------------------------------------------------------------------- 
1,2,3 red,blue,green 29,17,0 c,d,j nevada,california,utah 
+0

Я не совсем уверен, что вы пытаетесь сделать здесь, но если вы хотите исключить столбцы определенных типов данных, вы должны использовать столбец system_type_id. Если вы хотите, чтобы текстовое объяснение соединялось из sys.columns в sys.types. –

+0

@SeanLange Я больше беспокоюсь о проблеме рекурсивного подсчета наиболее часто встречающихся значений из всех столбцов таблицы (любая таблица) – Kristian

+0

Правильно ... это та часть, которую я сказал, что я не понимаю, что вы пытаетесь сделать , –

ответ

0

Start с этим SQL Statement строителем, и изменить его в соответствии с вашей симпатией:

EDIT Добавлено Сортировать по Описание изделия

With ColumnSet As 
(
    Select TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME 
    From INFORMATION_SCHEMA.COLUMNS 
    Where 1=1 
     And TABLE_NAME IN ('Table1') 
     And COLUMN_NAME IN ('Column1', 'Column2') 
) 
Select 'Select Top 3 ' + COLUMN_NAME + ', Count (*) NumInstances From ' + TABLE_SCHEMA + '.'+ TABLE_NAME + ' Group By ' + COLUMN_NAME + ' Order by Count (*) Desc' 
From ColumnSet 
+1

Вам нужно добавить заказ здесь.Это только начало, если я понимаю, что ищет OP. Для этого тогда потребуется использовать динамическую перекрестную вкладку или динамическую ось, чтобы вернуть значения в столбцы. –

+1

Я использовал бы порядок по count (*) вместо порядковой позиции. Гораздо реже, чтобы это случилось. :) –

1

я взломал это вместе, но это, кажется, работает:

Я не могу помочь, но думаю, что я должен использовать RANK().

USE <DB>; 

DECLARE @query nvarchar(max) 
DECLARE @column nvarchar(max) 
DECLARE @table nvarchar(max) 
DECLARE @i INT = 1 
DECLARE @maxi INT = 10 
DECLARE @target NVARCHAR(MAX) = <table> 

declare @stage TABLE (i int IDENTITY(1,1), col nvarchar(max), tbl nvarchar(max)) 
declare @results table (ColumnName nvarchar(max), ColumnValue nvarchar(max), ColumnCount int, TableName NVARCHAR(MAX)) 

insert into @stage 

select c.name, o.name 
    from sys.columns c 
    join sys.objects o on o.object_id=c.object_id and o.type = 'u' 
    and c.system_type_id IN (select system_type_id from sys.types where [name] not in ('text','ntext','image')) 
    and o.name like @target 



SET @maxi = (select max(i) from @stage) 

while @i <= @maxi 

BEGIN 

set @column = (select col from @stage where i = @i) 
set @table = (select tbl from @stage where i = @i) 


SET @query = N'SELECT ' +''''[email protected]+''''+' , '+ @column 

SELECT @query = @query + ', COUNT( ' + @column + ') as count' + @column + ' , ''' + @table + ''' as tablename' 
select @query = @query + ' from ' + @table + ' group by ' + @column 

--Select @query 
insert into @results 
EXEC sp_executesql @query 

SET @i = @i + 1 
END 

select * from @results 
; with cte as (
       select *, ROW_NUMBER() over (partition by Columnname order by ColumnCount desc) as rn from @results 
       ) 


select * from cte where rn <=3 
+0

спасибо! он, похоже, очень близок к работе, однако я получаю ошибку типа clash: 'timestamp несовместим с nvarchar (max)', любые предложения? – Kristian

+1

Я бы исключил временную метку вместе с текстом, текстом и изображением. Если вам это не нужно. –

+0

@ Eric_Hauenstein – Kristian

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