一直在努力解决这个问题,并且想请求帮助如何使这个查询发生。我的问题是在INNER JOIN子查询的WHERE部分中我需要使用来自每个正在处理的GC表行的匹配值,显然子查询对主查询一无所知,这就是它失败的原因。希望你能理解我想在这里实现的目标:
SET @now=100; #sunix datetime
SELECT a.id, b.maxdate
FROM GC AS a
INNER JOIN (
SELECT 0 id_group, MAX(dt_active_to) AS maxdate
FROM GCDeals
WHERE dt_active_from > a.dt_lastused AND dt_active_from <= @now
GROUP BY id_group
UNION ALL
SELECT 1 id_group, MAX(dt_active_to) AS maxdate
FROM GCDeals
WHERE id_group <> 2 AND dt_active_from > a.dt_lastused AND dt_active_from <= @now
UNION ALL
SELECT 2 id_group, MAX(dt_active_to) AS maxdate
FROM GCDeals
WHERE id_group <> 1 AND dt_active_from > a.dt_lastused AND dt_active_from <= @now
GROUP BY id_group
) AS b
ON a.id_group = b.id_group
LEFT JOIN GCMsg AS c
ON a.id = c.id_gc
WHERE a.is_active = 1 AND a.dt_lastused < @now AND c.id_gc IS NULL
ORDER BY a.id
谢谢
答案 0 :(得分:1)
好的,我希望我现在已经理解了你的原始SQL。您希望所有GC具有最后一个适当的最大日期。您认为合适的内容取决于gc.dt_lastused和gc.id_group。因此,您应该在子查询中选择每条记录的最大日期,而不是将表连接在一起:
select id,
(
select max(dt_active_to)
from gcdeals
where dt_active_from > gc.dt_lastused and dt_active_from <= @now
and
(
gc.id_group = 0)
or
(gc.id_group = 1 and gcdeals.id_group <> 2)
or
(gc.id_group = 2 and gcdeals.id_group <> 1)
)
) as maxdate
from gc
where is_active = 1 and dt_lastused < @now
and id not in (select id_gc from gcmsg)
order by id;
编辑:这是使用连接的相同语句,提供一次选择max(dt_active_from)和min(dt_active_to):
select gc.id, max(gcd.dt_active_from), min(gcd.dt_active_to)
from gc
left outer join gcdeals gcd
on gc.id = gcd.id_gc
and gcd.dt_active_from > gc.dt_lastused and gcd.dt_active_from <= @now
and
(
gc.id_group = 0)
or
(gc.id_group = 1 and gcd.id_group <> 2)
or
(gc.id_group = 2 and gcd.id_group <> 1)
)
where gc.is_active = 1 and gc.dt_lastused < @now
group by gc.id
order by gc.id;
您会看到,一旦您发现如何在子选择中选择所需的值,将其更改为连接并不太难。您可以通过两个步骤获得所需内容。另一方面,如果你开始考虑加入,同样的任务可能会非常抽象。
关于执行计划:Say GC有1000个活动记录,GCDeals中通常有大约10个适当的匹配。然后,第一个语句选择1,000条记录,并在每条记录上使用循环来访问GCDeals聚合值。第二个语句只会加入1,000个GC记录,每个记录包含10个GCDeals记录,从而获得10,000条记录,然后将它们聚合在一起,使其再次成为1,000条记录。也许循环更快,也许是连接。这取决于。但是,比方说,GC有一百万个活动记录,并且在每条记录上你预计会有1000个GCDeals匹配,那么第一个语句可能会非常缓慢地循环这么多次。但是第二个语句将创建十亿个中间记录,这些记录可能导致内存问题,并导致执行速度非常慢,甚至导致内存错误。所以我们很高兴知道这两种技术都可用。