SQL combine 2表和数据透视

SQL combine 2表和数据透视,sql,sql-server,pivot,Sql,Sql Server,Pivot,我不明白PIVOT在SQL中是如何工作的。我有两个表,我想对其中的一个表进行透视,以便只得到一个包含所有数据的表。我附上了一张图片,上面有我想要得到的表格和结果 CREATE TABLE TABLE1 ([serie_id] varchar(4), [Maturity] int, [Strategy] int, [Lifetime] varchar(4), [L_max] decimal(10, 5), [W_max] decimal(10, 5), [H_max] decimal(10

我不明白PIVOT在SQL中是如何工作的。我有两个表,我想对其中的一个表进行透视,以便只得到一个包含所有数据的表。我附上了一张图片,上面有我想要得到的表格和结果

CREATE TABLE TABLE1
    ([serie_id] varchar(4), [Maturity] int, [Strategy] int, [Lifetime] varchar(4), [L_max] decimal(10, 5), [W_max] decimal(10, 5), [H_max] decimal(10, 5))
;

INSERT INTO TABLE1
    ([serie_id], [Maturity], [Strategy], [Lifetime], [L_max], [W_max], [H_max])
VALUES
    ('id_1', 3, 1, '2', 2.200, 1.400, 1.400),
    ('id_2', 3, 1, '2', 3.400, 1.800, 2.100),
    ('id_3', 3, 1, NULL, 24.500, 14.500, 15.000),
    ('id_4', 3, 1, NULL, 28.000, 24.500, 14.000)
;

CREATE TABLE TABLE2
    ([serie_id] varchar(4), [L_value] decimal(10, 5), [lrms] decimal(10, 5), [latTmax] decimal(10, 5), [Rdc] decimal(10, 5))
;

INSERT INTO TABLE2
    ([serie_id], [L_value], [lrms], [latTmax], [Rdc])
VALUES
    ('id_1', 67.000, 400.000, 400.000, 0.250),
    ('id_1', 90.000, 330.000, 330.000, 0.350),
    ('id_1', 120.000, 370.000, 370.000, 0.300),
    ('id_1', 180.000, 330.000, 300.000, 0.350),
    ('id_2', 260.000, 300.000, 300.000, 0.400),
    ('id_2', 360.000, 280.000, 280.000, 0.450),
    ('id_3', 90.000, 370.000, 370.000, 0.300),
    ('id_4', 160.000, 340.000, 340.000, 0.400)
;


如果有人能在SQL查询方面帮助我,我将不胜感激。

为了得到最终结果,您必须实现多种方法,包括unpivot、pivot,以及使用诸如
行数()之类的窗口函数。

由于在
表2中有多个列需要进行数据透视,因此需要首先取消数据透视。这与pivot相反,pivot将多列转换为多行。但是在取消PIVOT之前,您需要一些值来使用
row\u number()
标识每行的值-听起来很复杂,对吗

首先,使用窗口功能
行编号()
查询
表2
。这将为每一行创建一个唯一的标识符,并允许您轻松地将
id_1
的值与其他任何一行相关联

select serie_id, l_value, lrms, latTmax, Rdc,
    rn = cast(row_number() over(partition by serie_id order by serie_id)
              as varchar(10))
from table2;
看。创建此唯一标识符后,您将
unpivot
L_值
lrms
latTmax
rdc
。您可以使用几种不同的方法取消分割数据,包括取消分割函数、交叉应用或联合全部

select serie_id,
  col, value
from
(
  select serie_id, l_value, lrms, latTmax, Rdc,
    rn = cast(row_number() over(partition by serie_id order by serie_id)
              as varchar(10))
  from table2 
) d
cross apply 
(
  select 'L_value_'+rn, L_value union all
  select 'lrms_'+rn, lrms union all
  select 'latTmax_'+rn, latTmax union all
  select 'Rdc_'+rn, Rdc
) c (col, value)
看。
表2
中的数据格式并非完全不同,可以旋转到新列中:

| SERIE_ID |       COL | VALUE |
|----------|-----------|-------|
|     id_1 | L_value_1 |    67 |
|     id_1 |    lrms_1 |   400 |
|     id_1 | latTmax_1 |   400 |
|     id_1 |     Rdc_1 |  0.25 |
|     id_1 | L_value_2 |    90 |
|     id_1 |    lrms_2 |   330 |
|     id_1 | latTmax_2 |   330 |
|     id_1 |     Rdc_2 |  0.35 |
最后一步是将上述数据转化为最终结果:

select serie_id, maturity, strategy, lifetime, l_max, w_max, h_max,
  L_value_1, lrms_1, latTmax_1, Rdc_1,
  L_value_2, lrms_2, latTmax_2, Rdc_2,
  L_value_3, lrms_3, latTmax_3, Rdc_3,
  L_value_4, lrms_4, latTmax_4, Rdc_4
from
(
  select t1.serie_id, t1.maturity, t1.strategy, t1.lifetime,
    t1.l_max, t1.w_max, t1.h_max,
    t2.col, t2.value
  from table1 t1
  inner join
  (
    select serie_id,
      col, value
    from
    (
      select serie_id, l_value, lrms, latTmax, Rdc,
        rn = cast(row_number() over(partition by serie_id order by serie_id)
                  as varchar(10))
      from table2 
    ) d
    cross apply 
    (
      select 'L_value_'+rn, L_value union all
      select 'lrms_'+rn, lrms union all
      select 'latTmax_'+rn, latTmax union all
      select 'Rdc_'+rn, Rdc
    ) c (col, value)
  ) t2
    on t1.serie_id = t2.serie_id
) d
pivot
(
  max(value)
  for col in (L_value_1, lrms_1, latTmax_1, Rdc_1,
              L_value_2, lrms_2, latTmax_2, Rdc_2,
              L_value_3, lrms_3, latTmax_3, Rdc_3,
              L_value_4, lrms_4, latTmax_4, Rdc_4)
) p;

如果在
表2中有未知数量的值,则需要使用动态SQL创建将要执行的SQL字符串。一旦逻辑正确,将上述代码转换为动态sql非常容易。守则如下:

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

select @cols 
    = STUFF((SELECT ',' + QUOTENAME(col+cast(rn as varchar(10))) 
             from 
             (
               select rn = cast(row_number() over(partition by serie_id order by serie_id)
                  as varchar(10))
               from table2
             ) d
             cross apply
             (
               select 'L_value_', 0 union all
                select 'lrms_', 1 union all
                select 'latTmax_', 2 union all
                select 'Rdc_', 3
             ) c (col, so)
             group by col, rn, so
             order by rn, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = N'SELECT serie_id, maturity, strategy, lifetime, l_max, 
                w_max, h_max,' + @cols + N' 
              from 
             (
               select t1.serie_id, t1.maturity, t1.strategy, t1.lifetime,
                t1.l_max, t1.w_max, t1.h_max,
                t2.col, t2.value
              from table1 t1
              inner join
              (
                select serie_id,
                  col, value
                from
                (
                  select serie_id, l_value, lrms, latTmax, Rdc,
                    rn = cast(row_number() over(partition by serie_id order by serie_id)
                              as varchar(10))
                  from table2 
                ) d
                cross apply 
                (
                  select ''L_value_''+rn, L_value union all
                  select ''lrms_''+rn, lrms union all
                  select ''latTmax_''+rn, latTmax union all
                  select ''Rdc_''+rn, Rdc
                ) c (col, value)
              ) t2
                on t1.serie_id = t2.serie_id
            ) x
            pivot 
            (
                max(value)
                for col in (' + @cols + N')
            ) p '

exec sp_executesql @query

两个版本都将给出以下结果:

| SERIE_ID | MATURITY | STRATEGY | LIFETIME | L_MAX | W_MAX | H_MAX | L_VALUE_1 | LRMS_1 | LATTMAX_1 | RDC_1 | L_VALUE_2 | LRMS_2 | LATTMAX_2 |  RDC_2 | L_VALUE_3 | LRMS_3 | LATTMAX_3 |  RDC_3 | L_VALUE_4 | LRMS_4 | LATTMAX_4 |  RDC_4 |
|----------|----------|----------|----------|-------|-------|-------|-----------|--------|-----------|-------|-----------|--------|-----------|--------|-----------|--------|-----------|--------|-----------|--------|-----------|--------|
|     id_1 |        3 |        1 |        2 |   2.2 |   1.4 |   1.4 |        67 |    400 |       400 |  0.25 |        90 |    330 |       330 |   0.35 |       120 |    370 |       370 |    0.3 |       180 |    330 |       300 |   0.35 |
|     id_2 |        3 |        1 |        2 |   3.4 |   1.8 |   2.1 |       260 |    300 |       300 |   0.4 |       360 |    280 |       280 |   0.45 |    (null) | (null) |    (null) | (null) |    (null) | (null) |    (null) | (null) |
|     id_3 |        3 |        1 |   (null) |  24.5 |  14.5 |    15 |        90 |    370 |       370 |   0.3 |    (null) | (null) |    (null) | (null) |    (null) | (null) |    (null) | (null) |    (null) | (null) |    (null) | (null) |
|     id_4 |        3 |        1 |   (null) |    28 |  24.5 |    14 |       160 |    340 |       340 |   0.4 |    (null) | (null) |    (null) | (null) |    (null) | (null) |    (null) | (null) |    (null) | (null) |    (null) | (null) |

问题是,我不知道如何获得“结果”表,以便在sqlfiddle中生成它,而不是使用sqlfiddle发布示例数据。。。出于这个原因,我认为在这方面比较容易way@user2528601对你来说更容易也许。。。其他可能帮助你的人更难:PID1有4条记录,但你的屏幕截图只显示了L_值最高和次高的两条记录。你是否只想限制在最高点和次最高点?还是要透视所有数据?@user2528601结果表可以作为图像、文本等。在SQLFIDLE中,源表可以作为起点。