将多个 self JOIN 转换为窗口函数或子查询 (SQL)

Posted

技术标签:

【中文标题】将多个 self JOIN 转换为窗口函数或子查询 (SQL)【英文标题】:Convert multiple self JOINs to window function or subqueries (SQL) 【发布时间】:2020-11-18 12:19:27 【问题描述】:

我有一个包含多个自连接的查询:

SELECT t2.Name, t2.Date as date, t2.Value as value1, t3.Value as value2, t4.Value as value3
FROM table_t t1
    RIGHT JOIN #tempPredefinedIndicators t2
        ON t1.Name = t2.Name
    JOIN #tempPredefinedIndicators t3 
        ON t2.Name = t3.Name AND t2.Date = t3.Date
    JOIN #tempPredefinedIndicators t4 
        ON t2.Name = t4.Name AND t2.Date = t4.Date    
WHERE t1.ValueName = 'one' AND DATEDIFF(year, ISDATE(t1.Value), GETDATE()) >=10
AND (t2.ValueName = 'two' AND TRY_CONVERT(FLOAT, t2.Value) > 0.15)
AND (t3.ValueName = 'three' AND TRY_CONVERT(FLOAT, t3.Value) BETWEEN 0 AND 0.5)
AND (t4.ValueName = 'four' AND TRY_CONVERT(FLOAT, t4.Value) > 0.15)

这是一个示例表,其中我用黄色标记了 where 条件边界内的记录:

这是预期的结果视图:

基本上我用几个连续的条件过滤一个表,并将结果显示为一个表。

有没有办法,使用窗口函数或子查询将其转换为更快?

【问题讨论】:

请提供样本数据和期望的结果。描述查询应该做什么。 似乎您正在使用数据透视/条件聚合; Stack Overflow 上有 100 个这样的例子。 我已经编辑了我的问题,以更好地阐明我在寻找什么。 见sqlblog.org/2009/11/19/what-is-so-bad-about-eav-anyway和softwareengineering.stackexchange.com/questions/93124/… 【参考方案1】:

您可以通过删除类型转换、向经常查询的相应列添加索引或将 4 表连接替换为 PIVOT 来提高性能。

SELECT * FROM (
  SELECT
    [name],
    [valuename],
    [value]
  FROM table_t
  WHERE 
    (valuename = 'one' and datediff(year, isdate(value), getdate()) > 10)
     or 
    (valuename = 'two' and TRY_CONVERT(FLOAT, Value) > 0.15)
     or 
    (ValueName = 'three' AND TRY_CONVERT(FLOAT, Value) BETWEEN 0 AND 0.5)
     or
    (ValueName = 'four' AND TRY_CONVERT(FLOAT, Value) > 0.15)
) a
PIVOT (
  MAX([value])
  FOR [valuename]
  IN (
    [one], [two], [three], [four]
  )
) AS PivotTable

在这里通过示例自学:https://www.sqlshack.com/dynamic-pivot-tables-in-sql-server/

您的查询在 sql-fiddle 中运行了 30 毫秒;在 WHERE 子句中运行无类型转换的数据只需要 17 毫秒,而在所有 WHERE 子句转换中运行需要 20-22 毫秒。

【讨论】:

谢谢。这对我来说非常有效,并且是我一直在寻找的简单性,但我在该领域缺乏知识是一个障碍。

以上是关于将多个 self JOIN 转换为窗口函数或子查询 (SQL)的主要内容,如果未能解决你的问题,请参考以下文章

如何将多个 INNER JOIN 转换为通用/可编程函数

索引视图在没有 INNER JOIN 或子查询的情况下查找空引用

如何将 CSV 数据导入多个数组并通过 VBA 中的函数或子函数返回多个数组?

Azure 流分析:多个 Windows JOIN 生成太多行

Clickhouse LEFT JOIN 部分匹配(或子选择)

如何使用“构造函数”在“选择子句”中为多个表的选定列编写HQL JOIN查询