【问题标题】:SQL Server get a certain row value as a column valueSQL Server 获取某行值作为列值
【发布时间】:2021-12-22 02:11:43
【问题描述】:

我有一张这样的桌子:

|  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  |

我想获得一个表格,其中列类型为“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 Server 数据透视函数,但无法获得所需的结果。

【问题讨论】:

  • 如何生成valuevalue_col 列;你写的什么查询不起作用。
  • 这里的逻辑是什么? b 类型的 ID 2、3 和 4 如何与 a 类型的 ID 1 和 b 的 6,7 与 a 的 5 匹配。你应该解释一下这种匹配的逻辑......
  • 嗨,Tom,您的问题是缺少一些内容,例如,如果您想将数据集转换为“类型”值,您想要进行的聚合(计算)是什么?例如,您想计算 'a' 类型机器的数量吗?或者你想在“价值”列上做一个总和、平均值等。您的问题缺少内容,请修改它或向我们提供 SQL 查询以帮助您。
  • ID 不相关,所以我不想选择它。该表包含一个值(类型 b)和一个阈值(类型 a)。每次机器上的阈值变化,都会记录在表中。但我想一次运行一个包含所有这些信息的查询。

标签: sql sql-server database data-science


【解决方案1】:

可以分三步完成,这让我觉得有更干净的方法(但我想不到)

  1. 创建一个标识符来关联所有应该共享a 值的行
  2. 使用窗口函数将 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


编辑

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


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

  • 因此,整个查询“花费”~20 次索引扫描

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

  • 因此,整个查询“花费”~8.3 次索引扫描

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

  • 我会针对您的实际数据运行一个实际的分析器
  • 如果性能很重要

(如果相关子查询方法“足够快”,请务必使用。)

【讨论】:

  • 我发现这个分析对于优化我的查询非常有用,谢谢!
  • 在检查逻辑读取和扫描计数时,交叉应用版本比分析函数版本获得的逻辑读取更少,这在考虑性能时是一件好事。 dbfiddle.uk/…
【解决方案2】:

使用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

【讨论】:

  • 肯定比使用分析函数更简洁。有兴趣在大型数据集上分析相关子查询的性能(其中分析函数的性质可能具有优势)
  • 要按machine 分区,这将在相关子查询中包含and x.machine = t.machine
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-07
  • 2011-12-27
  • 2016-11-19
  • 2015-06-21
  • 2014-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多