性能调优复杂 SQL 连接
Posted
技术标签:
【中文标题】性能调优复杂 SQL 连接【英文标题】:Performance tuning complex SQL join 【发布时间】:2020-09-25 12:20:59 【问题描述】:我正在尝试在 2 个表上进行连接。
表A
| date | var |
+------+-----+
| 1 | a |
| 2 | b |
| 3 | e |
| 4 | c |
| 5 | b |
表B
| date | var |
+------+-----+
| 1 | a |
| 2 | b |
| 3 | c |
| 3 | d |
我想进行内部连接,以便日期和 var 匹配,或者如果 tableA 中的日期大于 tableB 中的日期,则仅在 tableA 中的 var 与 tableB 中的 var 匹配,其中 tableB 中的日期为最大值。
输出表应该是:
| date | var |
+------+-----+
| 1 | a |
| 2 | b |
| 4 | c |
这是我想出的——但速度很慢:
select a.*
from tablea a
inner join tableb b on (a.var = b.var and a.date = b.date)
or (a.date > (select max(date) from tableb b)
and b.var in (select var from tableb having max(date)=date))
【问题讨论】:
用您正在使用的数据库标记您的问题。此外,显示您想要的结果。此外,您只是从a
中选择列,因此join
似乎没有必要。
列句号,在tableb中?
@jarlh Ups。类型。现已更正
@GordonLinoff 我正在尝试删除一些不匹配的列。我添加了输出表示例。希望这会让它更清楚。
请解释结果集中最后两行的逻辑:(3,e)和(4,c)
【参考方案1】:
像这样加入表格:
SELECT a.*
FROM TableA a INNER JOIN TableB b
ON a.var = b.var AND b.date = (SELECT MAX(date) FROM TableB WHERE a.date >= date)
请参阅demo。 结果:
> date | var
> ---: | :--
> 1 | a
> 2 | b
> 4 | c
【讨论】:
如果这是你的意思,那么是的。但是您原来的 sql 暗示了一些不同的东西,请参阅下面的答案。它会为您提供的数据集返回相同的结果,但会为不同的数据集返回不同的结果。您应该澄清您的规范以表明您的意思。【参考方案2】:如果不知道确切的架构(包括索引),就很难预测性能。总的来说,我敢打赌下面的查询会更高效。
DECLARE @a TABLE(date INT, var NVARCHAR(1))
INSERT @a VALUES(1,'a'),(2,'b'),(3,'e'),(4,'c'), (5,'b')
DECLARE @b TABLE(date INT, var NVARCHAR(1))
INSERT @b VALUES(1,'a'),(2,'b'),(3,'c'),(3,'d')
;
WITH b AS
(
select * from(
select var,date,dateRankReveresed = rank() OVER(ORDER BY date DESC)
from @b
)as x
)
select a.*
from
@a a
inner join b b on a.var=b.var
and
((a.date=b.date)
or
((a.date > b.date and b.dateRankReveresed=1)))
编辑:在这种情况下,请使用 rank 而不是 row_number,因为您需要 dups 的关系。
【讨论】:
【参考方案3】:您的 sql 在 mysql 中不起作用,但我将其更改为:
select a.*
from TableA a
inner join TableB b on (a.var = b.var and a.dat = b.dat) OR (a.dat > (select
max(dat) from TableB)
and b.var in (select var from TableB where TableB.dat=
(select max(dat) from TableB)));
但这样我会得到更多的结果。
'1', 'a'
'2', 'b'
'4', 'c'
'4', 'c'
'5', 'b'
'5', 'b'
相反,我认为你想要:
select a.*
from TableA a
where (a.dat > (select max(dat) from TableB)
and a.var in (select var from TableB
where TableB.dat=(select max(dat) from TableB)))
union select a.* from TableA a inner join TableB b where a.var=b.var and
a.dat=b.dat;
【讨论】:
以上是关于性能调优复杂 SQL 连接的主要内容,如果未能解决你的问题,请参考以下文章