SQL服务器获取某行值作为列值

SQL Server get a certain row value as a column value

我有一个像这样的table:

|  machine  |  type  |    value  |  id  |
+-----------+--------+-----------+------+
|     1     |   a    |     0.34  |   1  |
|     1     |   b    |     0.23  |   2  |
|     1     |   b    |     0.26  |   3  |
|     1     |   b    |     0.35  |   4  |
|     1     |   a    |     0.15  |   5  |
|     1     |   b    |     0.45  |   6  |
|     1     |   b    |     0.55  |   7  |

并且我想获得一个 table,其中类型为“a”的行作为列(id 在这种情况下不相关)。例如:

|  machine  |  value | value_col |
+-----------+--------+-----------+
|     1     |   0.23 |  0.34     |
|     1     |   0.26 |  0.34     |
|     1     |   0.35 |  0.34     |
|     1     |   0.45 |  0.15     |
|     1     |   0.55 |  0.15     |

我尝试了 SQL 服务器数据透视功能,但无法获得所需的结果。

分三步搞定,感觉还有更简洁的方法(但想不出来)

  1. 创建一个标识符来关联应该共享一个 a 值的所有行
  2. 使用 window 函数将 a 值复制到分区的其余部分
  3. 过滤以仅包含 b

例如...

WITH
  a_partitioned AS
(
  SELECT
    *,
    SUM(CASE WHEN type='a' THEN 1 ELSE 0 END) OVER (PARTITION BY machine ORDER BY id)  AS a_partition
  FROM
    your_table
),
  a_value_spread AS
(
  SELECT
    *,
    MAX(CASE WHEN type = 'a' THEN value END) OVER (PARTITION BY machine, a_partition)  AS a_value
  FROM
    a_partitioned 
)
SELECT
  *
FROM
  a_value_spread
WHERE
  type = 'b'

演示:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=9037c0d3e6d46e05ecbcfdd3777808cd


编辑

这是我的 REALLY 肤浅的尝试,尝试用哪个答案可能具有最低的处理开销...


关联子查询版本中,数据的扫描占总成本的4%

  • 所以,整个查询 'costs' ~20 索引扫描

解析函数版中,数据的扫描占总成本的12%

  • 所以,整个查询 'costs' ~8.3 索引扫描

虽然这是一个非常小的数据集,而且是一个非常随意构造的数据集。

  • 我会运行根据您的实际数据进行实际分析
  • IF 性能很重要

(如果相关子查询方式是'fast enough',一定要用那个。)

使用CROSS APPLY()获取最后的a

select t.machine, t.value, v.value_col
from   tbl t
       cross apply
       (
           select top 1 value_col = value
           from   tbl x
           where  x.id < t.id
           and    x.type = 'a'
           order by id desc
       ) v
where  t.type = 'b'

dbfiddle