我使用的是oracle sql开发人员。 我有一个疑问,有一件事我有点麻烦: 1)我需要做一个有一些规则的选择。
如果不清楚我已经制作了一个,那可行,但它有点愚蠢,因为我认为有一些方法可以做到这一点,或者更有效或更具可读性,因为这种方式我不得不重写几乎同样选择两次:
SELECT *
FROM TABLE1
WHERE NRSEQTABLE1 IN
(SELECT DECODE(T1.NRSEQTABLE1,NULL, T2.NRSEQTABLE1, T1.NRSEQTABLE1) AS NRSEQTABLE1
FROM
(SELECT NRSEQTABLE1,
NRNUM2
FROM TABLE1 T1
WHERE TO_CHAR(DTHRTABLE1, 'MM/YYYY') = TO_CHAR(SYSDATE, 'MM/YYYY')
AND IDRULE = 'NO'
) T1
FULL JOIN
(SELECT NRSEQTABLE1,
NRNUM2
FROM TABLE2 T2
WHERE TO_CHAR(DTHRTABLE2, 'MM/YYYY') = TO_CHAR(SYSDATE, 'MM/YYYY')
AND IDRULE = 'NO'
) T2
ON T2.NRSEQTABLE1 = T1.NRSEQTABLE1
AND T2.NRNUM2 = T1.NRNUM2
)
AND NRGROUPBY IN
(SELECT NRGROUPBY
FROM TABLE1
WHERE NRSEQTABLE1 IN
(SELECT DECODE(T1.NRSEQTABLE1,NULL, T2.NRSEQTABLE1, T1.NRSEQTABLE1) AS NRSEQTABLE1
FROM
(SELECT NRSEQTABLE1,
NRNUM2
FROM TABLE1 T1
WHERE TO_CHAR(DTHRTABLE1, 'MM/YYYY') = TO_CHAR(SYSDATE, 'MM/YYYY')
AND IDRULE = 'NO'
) T1
FULL JOIN
(SELECT NRSEQTABLE1,
NRNUM2
FROM TABLE2 T2
WHERE TO_CHAR(DTHRTABLE2, 'MM/YYYY') = TO_CHAR(SYSDATE, 'MM/YYYY')
AND IDRULE = 'NO'
) T2
ON T2.NRSEQTABLE1 = T1.NRSEQTABLE1
AND T2.NRNUM2 = T1.NRNUM2
)
GROUP BY TABLE1.NRGROUPBY
HAVING COUNT(TABLE1.NRSEQTABLE1) > 10
)
ORDER BY NRGROUPBY,
NRSEQTABLE1;
对不起英语,感谢您的帮助
答案 0 :(得分:3)
1 评估日期是否属于当月的一个好方法应该避免在列值上调用函数。你应该切换
TO_CHAR(DTHRTABLE1, 'MM/YYYY') = TO_CHAR(SYSDATE, 'MM/YYYY')
带
DTHRTABLE1 >= trunc(SYSDATE, 'MM') and DTHRTABLE1 < add_months(trunc(SYSDATE, 'MM'), 1)
允许优化器最终使用索引,并且每次查询执行只评估一次函数,而不是每个表行一次。
2 没有必要为您的目的执行任何完整加入。那些
where id in (
select id
from a
full join b using (id...)
)
是精神上的做法
where id in (
select id
from a
)
or id in (
select id
from b
)
3 第二个子查询与查询的第一部分显着相同,因此您可以使用子查询因子来不对其进行两次计算。所以你可以切换
select id1, id2, xyx
from a
where (
id1 in (
select id1
from a
)
or id1 in (
select id1
from b
)
)
and id2 in (
select id2
from a
where (
id1 in (
select id1
from a
)
or id1 in (
select id1
from b
)
)
group by id2
having xyz2
)
到
with src as (
select id1, id2, xyx
from a
where (
id1 in (
select id1
from a
)
or id1 in (
select id1
from b
)
)
)
select *
from src
where id2 in (
select id2
from src
group by id2
having xyz
)
5 但是,一旦通过联接的自我组变得如此明确,你可以将该模式切换到分析等效的女巫比它更快
select id1, id2, xyx
from (
select id1, id2, xyx,
COUNT(NRSEQTABLE1) over (partition by NRGROUPBY) as cnt
from a
where (
id1 in (
select id1
from a
)
or id1 in (
select id1
from b
)
)
)
where cnt > 10
如果您提供有关所涉及列的唯一性的详细信息(特别是NRSEQTABLE1,NRNUM2和NRGROUPBY),我可以建议您提高性能的一些可能更好的方法,但目前您可以尝试此查询:
select *
from (
SELECT t.*,
COUNT(NRSEQTABLE1) over (partition by NRGROUPBY) as cnt
FROM TABLE1 t
WHERE NRSEQTABLE1 IN (
SELECT NRSEQTABLE1
FROM TABLE1 T1
WHERE DTHRTABLE1 >= trunc(SYSDATE, 'MM') and DTHRTABLE1 < add_months(trunc(SYSDATE, 'MM'), 1)
AND IDRULE = 'NO'
)
OR NRSEQTABLE1 IN (
SELECT NRSEQTABLE1
FROM TABLE2 T2
WHERE DTHRTABLE2 >= trunc(SYSDATE, 'MM') and DTHRTABLE2 < add_months(trunc(SYSDATE, 'MM'), 1)
AND IDRULE = 'NO'
)
)
where cnt > 10
<强>更新强>
鉴于&#34; NRSEQTABLE1是来自table1的唯一Pk,但在table2中它是fk&#34;
第一个子查询可能没用,因为TABLE1的那些行
NRSEQTABLE1 IN (
SELECT NRSEQTABLE1
FROM TABLE1 T1
WHERE DTHRTABLE1 >= trunc(SYSDATE, 'MM') and DTHRTABLE1 < add_months(trunc(SYSDATE, 'MM'), 1)
AND IDRULE = 'NO'
)
正是那些
的那些DTHRTABLE1 >= trunc(SYSDATE, 'MM') and DTHRTABLE1 < add_months(trunc(SYSDATE, 'MM'), 1)
AND IDRULE = 'NO'
然后你的查询将是
select *
from (
SELECT t.*,
COUNT(NRSEQTABLE1) over (partition by NRGROUPBY) as cnt
FROM TABLE1 t
WHERE (
DTHRTABLE1 >= trunc(SYSDATE, 'MM') and DTHRTABLE1 < add_months(trunc(SYSDATE, 'MM'), 1)
AND IDRULE = 'NO'
)
OR NRSEQTABLE1 IN (
SELECT NRSEQTABLE1
FROM TABLE2 T2
WHERE DTHRTABLE2 >= trunc(SYSDATE, 'MM') and DTHRTABLE2 < add_months(trunc(SYSDATE, 'MM'), 1)
AND IDRULE = 'NO'
)
)
where cnt > 10
更仔细地阅读你的问题,我注意到你说&#34;两个表中的idrule一定不能没有#34; ,但是这个查询(因此也是原始的查询)不是&为此目的是正确的,因为它检查&#34; idrule是否等于&#39; NO&#39;在TABLE1和TABLE2 &#34;中的任何一个表中至少一次。
答案 1 :(得分:1)
您可以使用CTE上也知道的WITH
条款。就是这个:
with t1 as
(SELECT NRSEQTABLE1, NRNUM2
FROM TABLE1 T1
WHERE TO_CHAR(DTHRTABLE1, 'MM/YYYY') = TO_CHAR(SYSDATE, 'MM/YYYY')
AND IDRULE = 'NO'),
t2 as
(SELECT NRSEQTABLE1, NRNUM2
FROM TABLE2 T2
WHERE TO_CHAR(DTHRTABLE2, 'MM/YYYY') = TO_CHAR(SYSDATE, 'MM/YYYY')
AND IDRULE = 'NO'),
t3 as
(select DECODE(T1.NRSEQTABLE1,NULL, T2.NRSEQTABLE1, T1.NRSEQTABLE1) AS NRSEQTABLE1
from T1 FULL JOIN T2
ON T2.NRSEQTABLE1 = T1.NRSEQTABLE1
AND T2.NRNUM2 = T1.NRNUM2),
t4 as
(SELECT NRGROUPBY
FROM TABLE1
WHERE NRSEQTABLE1 IN
(select NRSEQTABLE1 from t3)
GROUP BY TABLE1.NRGROUPBY
HAVING COUNT(TABLE1.NRSEQTABLE1) > 10)
SELECT *
FROM TABLE1
WHERE NRSEQTABLE1 IN (select NRSEQTABLE1 from t3)
AND NRGROUPBY IN (select NRGROUPBY from t4)
ORDER BY NRGROUPBY, NRSEQTABLE1;
通常它更容易阅读,并且很多时候它会提高性能,因为Oracle可以动态创建临时表来存储一些数据。
注意,上面的查询可能包含错误,我只是在没有任何测试的情况下快速完成。但是,您应该了解它的外观。