0

我有:
items由一组 id 描述(GroupType、ID、Name)

VALUES在每个日期填充因子值的表,以便项目仅获得具有每个日期值的特定因子集。

FACTORS包含因子的静态描述的表。


寻找:

我想创建一个临时表,其中包含一个显示每个日期每个项目的因子值的矩阵,以便人们可以以用户友好的方式查看在给定日期填充了哪些因子(具有相应的值)。

价值观

Date        GroupType   ID  Name   FactorId  Value
01/01/2013        1     1   A      1         10
01/01/2013        1     1   A      2         8
01/01/2013        1     1   A      3         12

01/01/2013        1     2   B      3         5
01/01/2013        1     2   B      4         6

02/01/2013        1     1   A      1         7
02/01/2013        1     1   A      2         6

02/01/2013        1     2   B      3         9
02/01/2013        1     2   B      4         9

因素

FactorId FactorName 
1     Factor1
2     Factor2
3     Factor3
4     Factor4
.     .
.     .
.     .

临时表因子值矩阵

Date          Group       ID     Name  Factor1    Factor2      Factor3     Factor4  Factor...
01/01/2013        1        1        A       10          8           12
01/01/2013        1        2        B                                5           6

02/01/2013        1        1        A        7          6           
02/01/2013        1        2        B                                9           9

任何帮助是极大的赞赏!

4

2 回答 2

2

这种类型的数据转换称为 a PIVOT,它从行中获取值并将其转换为列。

在 SQL Server 2005+ 中,有一个函数可以执行这种数据轮换。

静态枢轴:

如果您的值将被设置,那么您可以FactorNames使用静态枢轴将其硬编码到列中。

select date, grouptype, id, name, Factor1, Factor2, Factor3, Factor4
from
(
  select v.date,
    v.grouptype,
    v.id,
    v.name,
    f.factorname,
    v.value
  from [values] v
  left join factors f 
    on v.factorid = f.factorid
  -- where v.date between date1 and date2
) src
pivot
(
  max(value)
  for factorname in (Factor1, Factor2, Factor3, Factor4)
) piv;

请参阅SQL Fiddle with Demo

动态枢轴:

在您的情况下,您声明您将拥有未知数量的值。如果是这样,那么您将需要使用动态 SQL 来生成将在运行时执行的 SQL 字符串:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(FactorName) 
                    from factors
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT date, grouptype, id, name,' + @cols + ' from 
             (
                select v.date,
                  v.grouptype,
                  v.id,
                  v.name,
                  f.factorname,
                  v.value
                from [values] v
                left join factors f 
                  on v.factorid = f.factorid
                -- where v.date between date1 and date2
            ) x
            pivot 
            (
                max(value)
                for factorname in (' + @cols + ')
            ) p '

execute(@query)

请参阅SQL Fiddle with Demo

这两个版本都产生相同的结果:

|       DATE | GROUPTYPE | ID | NAME | FACTOR1 | FACTOR2 | FACTOR3 | FACTOR4 |
------------------------------------------------------------------------------
| 2013-01-01 |         1 |  1 |    A |      10 |       8 |      12 |  (null) |
| 2013-01-01 |         1 |  2 |    B |  (null) |  (null) |       5 |       6 |
| 2013-02-01 |         1 |  1 |    A |       7 |       6 |      11 |  (null) |
| 2013-02-01 |         1 |  1 |    B |  (null) |  (null) |       9 |       9 |

如果要根据日期范围过滤结果,则只需WHERE在上述查询中添加一个子句。

于 2013-02-04T10:40:28.643 回答
0

看起来您只是想将行转换为列。我认为这可以满足您的要求:

select Date, Group, ID, Name, 
       max(case when factorid = 1 then name end) as Factor1,
       max(case when factorid = 2 then name end) as Factor2,
       max(case when factorid = 3 then name end) as Factor3,
       max(case when factorid = 4 then name end) as Factor4
from t
group by Date, Group, ID, Name
于 2013-02-04T03:24:10.553 回答