计算不同的多列模式

时间:2015-01-13 16:45:56

标签: sql-server-2014

我正在使用SQL Server 2014,并且我需要一些有关硬查询的帮助。

我有下表(MyTable)。这些列名称仅用于示例。它们实际上彼此完全不同。

id int,
col1 int,
col2 int,
..
..
..
col70 int

对于每对连续列{(col1,col2),(col2_col3)...(col69_col70)},我需要计算以下内容:每个值具有的不同对的数量 - col_i是静态列,col_i + 1是另一个。每个值需要除以表中记录的总量。例如:

col1 | col2
45   | 789
56   | 345
99   | 234
45   | 789
45   | 222
89   | 678
89   | 345
45   | 789
90   | 234
12   | 567

计算:

((45, 789)+(45, 222))/10
(56, 345)/10
(99, 234)/10
(45, 789)+(45, 222)/10
(45, 789)+(45, 222)/10
(89, 678)+(89, 345)/10
(89, 678)+(89, 345)/10
((45, 789)+(45, 222))/10
(90, 234)/10
(12, 567)/10

输出:

col1_col2
    0.2
    0.1
    0.1
    0.2
    0.2
    0.2
    0.2
    0.2
    0.1
    0.1

第一条记录的说明: 45是静态列的值,所以现在我要检查我们可以用col2找到多少个不同的组合:

45   | 789
45   | 789
45   | 222
45   | 789

总的不同组合除以表格中的记录数量:2/10 = 0.2

此计算需要每对连续列。有什么建议?是否有一种智能的方法来自动计算它而不是为每对写一行查询?

1 个答案:

答案 0 :(得分:0)

假设您有一个主键的示例:

create table my_table
(column_id int not null,
column1 int not null,
column2 int not null);

insert into my_table
(column_id, column1, column2)
values
(1, 45,789),
(2, 56,345),
(3, 99,234),
(4, 45,789),
(5, 45,222),
(6, 89,678),
(7, 89,345),
(8, 45,789),
(9, 90,234),
(10, 12,567);

declare @column_a as nvarchar(100) = N'column1';
declare @column_b as nvarchar(100) = N'column2';
declare @result_column as nvarchar(100) = N'column1_2';
declare @sql_string as nvarchar(4000)

set @sql_string = 
'select a.column_id,
1.0 * count( distinct b.' + @column_b + ') / (count(a.' + @column_a + ') over ()) as ' + @result_column 
+ ' from my_table a
inner join my_table b
on a.' + @column_a + ' = b.' + @column_a +
' group by a.column_id, a.' + @column_a + 
' order by a.column_id';

-- print @sql_string;
execute(@sql_string);

如果没有主键,您可以使用rownumber()函数创建标识符,但结果顺序会发生变化。 print命令可用于检查动态sql字符串,此处已注释掉。

将动态SQL放入存储过程:

create procedure column_freq @column_a nvarchar(100), @column_b nvarchar(100), @result_column nvarchar(100)
as
begin
    declare @sql_string as nvarchar(4000);

    set @sql_string = 
    'select a.column_id,
    1.0 * count( distinct b.' + @column_b + ') / (count(a.' + @column_a + ') over ()) as ' + @result_column 
    + ' from my_table a
    inner join my_table b
    on a.' + @column_a + ' = b.' + @column_a +
    ' group by a.column_id, a.' + @column_a + 
    ' order by a.column_id';

    execute(@sql_string);
end;
go

exec column_freq N'column1', N'column2', N'column1_2';
go