我有一个非常slooowwwww查询。
它选择具有组合标准的客户记录,有点像这样:
表格有Customers
,另一个表格有CustomerCars
,另一个表格有CustomerMotorcycles
。
客户可以拥有一辆或多辆汽车。如果客户是商业企业,并且任何一个客户的汽车都是福特汽车,那么我们希望从我们的选择中排除该客户。
客户也可以拥有一辆或多辆摩托车,如果客户是零售企业且其任何一辆摩托车是哈雷,那么我们希望将该客户排除在外。
所以我有一个声明:
SELECT *
FROM CUST
WHERE
(CUST.CUSTTYPE = 'COMM'
AND CUST.CUSTID NOT IN (SELECT CUSTCARS.CUSTID
FROM CUSTCARS
WHERE CUSTCARS.CAR = 'FORD'))
OR
(CUST.CUSTTYPE = 'RETAIL'
AND CUST.CUSTID NOT IN (SELECT CUSTCYCLES.CUSTID
FROM CUSTCYCLES
WHERE CUSTCYCLES.CYCLE = 'HARLEY'))
这很疯狂。
这当前是作为一堆将数据转储到临时表中的单独查询运行的,然后运行其他几个查询来删除我们不想要的记录,但它非常笨拙。
有什么建议吗?谢谢你的帮助!
答案 0 :(得分:1)
尝试"离开连接",我们离开加入匹配我们不想要的条件的数据,然后通过where子句排除匹配的行:
SELECT
CUST.*
FROM CUST
LEFT JOIN CUSTCARS ON CUST.CUSTID = CUSTCARS.CUSTID
AND CUSTCARS.CAR = 'FORD'
AND CUST.CUSTTYPE = 'COMM'
LEFT JOIN CUSTCYCLES ON CUST.CUSTID = CUSTCYCLES.CUSTID
AND CUSTCYCLES.CYCLE = 'HARLEY'
AND CUST.CUSTTYPE = 'RETAIL'
WHERE CUSTCARS.CUSTID IS NULL
OR CUSTCYCLES.CUSTID IS NULL
;
虽然我在这里,但现有查询中的OR可能导致过度缓慢(可能),因此将2个子查询组合到一个列表中可能会有所帮助:
SELECT
*
FROM CUST
WHERE CUSTID NOT IN (
SELECT
CUSTCARS.CUSTID
FROM CUSTCARS
INNER JOIN CUST ON CUSTCARS.CUSTID = CUST.CUSTID
WHERE CUSTCARS.CAR = 'FORD'
AND CUST.CUSTTYPE = 'COMM'
UNION ALL
SELECT
CUSTCYCLES.CUSTID
FROM CUSTCYCLES
INNER JOIN CUST ON CUSTCYCLES.CUSTID = CUST.CUSTID
WHERE CUSTCYCLES.CYCLE = 'HARLEY'
AND CUST.CUSTTYPE = 'RETAIL'
)
;
答案 1 :(得分:0)
我建议从not exists
开始:
select c.*
from cust c
where not (c.custtype = 'COMM' and
exists (select 1
from custcars cc
where cc.custid =c.custid and cc.car = 'FORD'
)
) and
not (c.custtype = 'RETAIL' and
exists (select 1
from custcycles cc
where cc.custid = c.custid and cc.cycle = 'HARLEY'
)
) ;
然后,您要确保在custcar(custid, car)
和custcycles(custid, cycle)
上有索引。
答案 2 :(得分:0)
有两件事情浮现在脑海中。首先,确保有CUSTCARS.CAR和CUSTCYCLES.CYCLE的索引。其次,您可以尝试NOT EXISTS而不是NOT IN。
SELECT * FROM CUST
WHERE
(CUST.CUSTTYPE = 'COMM'
AND NOT EXISTS(SELECT 1 FROM CUSTCARS WHERE CUSTCARS.CAR = 'FORD'
AND CUSTCARS.CUSTID=CUST.CUSTID))
OR
(CUST.CUSTTYPE = 'RETAIL'
AND NOT EXISTS(SELECT 1 FROM CUSTCYCLES WHERE CUSTCYCLES.CYCLE = 'HARLEY'
AND CUSTCYCLES.CUSTID=CUST.CUSTID))