将多个 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 或子查询的情况下查找空引用
如何将 CSV 数据导入多个数组并通过 VBA 中的函数或子函数返回多个数组?
Azure 流分析:多个 Windows JOIN 生成太多行