我有类似以下结构:Table1 - >表2的关系是1:m
我需要执行类似下一个的查询:
select Table1.id from Table1 left outer join Table2 on (Table1.id1 = Table2.id2) where Table2.name like '%a%' and rownum < 11
即。我希望表1中的前10个ID满足表2中的条件。问题是我要使用distinct,但在rownum&lt;之后应用distinct子句。 11',结果可能是例如5条记录,即使它们的数量超过10条。
明显的解决方案是使用以下内容:
select id from ( select Table1.id from Table1 left outer join Table2 on (Table1.id1 = Table2.id2) where Table2.name like '%a%' ) where rownum < 11
但我害怕这种查询的表现。如果Table1包含大约300k记录,而Table2包含大约700k记录,那么这样的查询是不是真的很慢?
是否有其他查询,但没有内部选择?不幸的是,我想避免使用内部选择。
答案 0 :(得分:3)
不幸的是,我想避免使用内心 选择
在TABLE2上使用WHERE子句,您将select过滤到INNER JOIN(即,因为Table2.name IS null&lt;&gt; Table2.name,如'%a%',您将只获得连接的结果彼此是INNER。另外,没有基于函数的索引的%a%将导致每次迭代都进行全表扫描。
但@lweller完全正确,要正确执行查询,您需要使用子查询。请记住,没有ORDER BY你不能保证你的前X记录的顺序(它可能总是'显示'值符合主键或诸如此类的东西,但不能保证。
WITH TABLE1 AS(SELECT 1 ID FROM DUAL
UNION ALL
SELECT 2 ID FROM DUAL
UNION ALL
SELECT 3 ID FROM DUAL
UNION ALL
SELECT 4 ID FROM DUAL
UNION ALL
SELECT 5 ID FROM DUAL) ,
TABLE2 AS(SELECT 1 ID, 'AAA' NAME FROM DUAL
UNION ALL
SELECT 2 ID, 'ABB' NAME FROM DUAL
UNION ALL
SELECT 3 ID, 'ACC' NAME FROM DUAL
UNION ALL
SELECT 4 ID, 'ADD' NAME FROM DUAL
UNION ALL
SELECT 1 ID, 'BBB' NAME FROM DUAL
) ,
sortable as( --here is the subquery
SELECT
Table1.ID ,
ROW_NUMBER( ) OVER (ORDER BY Table2.NAME NULLS LAST) ROWOverName , --this wil handle the sort
table2.name
from
Table1
LEFT OUTER JOIN --this left join it moot, pull the WHERE table2.name into the join to have it LEFT join as expected
Table2
on
(
Table1.id = Table2.id
)
WHERE
Table2.NAME LIKE '%A%')
SELECT *
FROM sortable
WHERE ROWOverName <= 2;
- 您可以删除ROW_NUMBER()分析函数并替换最终查询(如您最初指示的那样)
SELECT *
FROM sortable
WHERE
ROWNUM <= 2
ORDER BY sortable.NAME --make sure to put in an order by!
;
答案 1 :(得分:2)
这里根本不需要DISTINCT
,子查询也没有什么不好。
SELECT id
FROM Table1
WHERE id IN
(
SELECT id
FROM Table2
WHERE name LIKE '%a%'
)
AND rownum < 11
请注意,订单无法保证。为了保证订单,您必须使用嵌套查询:
SELECT id
FROM (
SELECT id
FROM Table1
WHERE id IN
(
SELECT id
FROM Table2
WHERE name LIKE '%a%'
)
ORDER BY
id -- or whatever else
)
WHERE rownum < 11
没有嵌套查询(或CTE
),就无法做到这一点。
答案 2 :(得分:1)
对我来说,没有理由害怕表现。我认为子选择是解决问题的最佳方法。如果您不想相信我,请查看您的查询的解释计划,您会发现它的行为并不像您想象的那么糟糕。