【问题标题】:Sprade distinct values over a different columns在不同的列上散布不同的值
【发布时间】:2014-11-20 13:25:22
【问题描述】:

我正在使用 SQL Server。我有下表(MyTable):

ID (int)
value (varchar)

我有以下疑问:

select distinct value
from MyTable 

输出是:

Value_1
Value_2
Value_3
...
...
...
Value_450

我想创建下表(当 value = 'value_1' then 1 else o...):

ID | Value_1 | Value_2 | Value_3 | Value_4 | .... | Value_450
1  |   0     |    1    |    0    |   0     | .... |   0
2  |   0     |    0    |    0    |   1     | .... |   0
3  |   1     |    0    |    0    |   0     | .... |   0
4  |   0     |    1    |    0    |   0     | .... |   0
5  |   0     |    0    |    0    |   0     | .... |   1
6  |   1     |    0    |    0    |   0     | .... |   0
7  |   0     |    0    |    0    |   1     | .... |   0
8  |   0     |    0    |    0    |   0     | .... |   1

如果value 的不同值很小,我会使用Case 语句进行查询。在这种我有这么多价值观的情况下,我该怎么办?有什么聪明的方法吗?

【问题讨论】:

  • 您使用的是什么关系型数据库?
  • 我正在使用 SQL Server
  • 查找 PIVOT,但我会质疑拥有 450 列的有用性!

标签: sql sql-server tsql case distinct


【解决方案1】:

可以用动态sql来完成

declare @query varchar(max);
declare @values varchar(max) = null;

with distinctValues as
(
    select distinct cast(value as varchar(20)) as value from myTable
)
select @values = COALESCE(@values + ', ['+ value + ']', '['+ value + ']') 
from distinctValues;

set @query = 'select [id], ' + @values +
'from myTable pivot ( count(value) for value in (' + @values + ')) as pvt';

exec(@query);

回答 cmets 提出的其他问题:

您可以使用INSERT ... EXEC 语法将动态查询的结果插入到表中:

insert into myOtherTable 
/* specify columns here if result does not have the same structure as the table */
exec(@query);

您说您有多个 (6) 列与您的示例中的 value 列具有相同的作用。我假设列的名称是已知的并且不会变化。所以表结构是:

id, value1, value2, value3, value4, value5, value6

据我了解,结果必须如下所示:

id, v1, v2, v3, ..., vn

其中v1, v2, v3, ..., vn 是可以在列value1, value2, value3, value4, value5, value6 上找到的所有不同值

在这种情况下,您必须首先使用UNPIVOT

declare @query varchar(max);
declare @values varchar(max) = null;

with distinctValues as
(
    select distinct cast(value as varchar(20)) as value 
    from myTable
    UNPIVOT
    (
       value for col in (value1, value2, value3, value4, value5, value6)
    ) as upvt
)
select @values = COALESCE(@values + ', ['+ value + ']', '['+ value + ']') 
from distinctValues;



set @query = 
';with myTableUnpivoted as 
( 
   select id, value 
   from myTable 
   UNPIVOT 
   ( 
      value for col in (value1, value2, value3, value4, value5, value6) 
   ) as upvt 
) 
select [id], ' + @values +
'from myTableUnpivoted pivot ( count(value) for value in (' + @values + ')) as pvt';

-- insert into myOtherTable
exec(@query);

请注意,UNPIVOT 操作执行了两次。

您可以将未透视表存储在临时表中。检查这是否会提高性能。

【讨论】:

  • 哇,伙计。惊人的解决方案。我刚刚检查过,效果很好!谢谢!实际上我需要在 6 个不同的列上运行此查询(值列是 6 个不同的列。每列都有自己不同的值)。是否可以一次将您的查询用于 6 个不同的列?
  • 你必须更好地解释(也许用另一个例子)你的表结构是什么以及预期的结果是什么。
  • 它与我原来的帖子中的结构和预期结果相同。在这种情况下,我没有在 MyTable 中有“值”列,而是有 6 个不同的值列(Value_1、value_2...value_6)。每个 Value 列都有自己的不同值(列之间可能相似。例如:Value_1 和 Value_2 列可以具有相同的值)。如果每列有 50 个不同的值,则预期结果是 450 列。希望它足够清楚。
  • 我可以使用您的查询 6 次,每次在不同的列上,然后加入输出表。一次将查询用于 6 个不同的列会更明智。
  • 还有一件事 - 我无法将输出插入到表格中。我尝试使用“select * into table”,但它不起作用。
猜你喜欢
  • 2015-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-14
  • 2018-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多