提问人:dougp 提问时间:11/16/2023 最后编辑:dougp 更新时间:11/20/2023 访问量:75
不符合的 SQL 语法 [已关闭]
non-conforming SQL syntax [closed]
问:
我正在使用供应商软件,该软件使我能够根据其现代 Oracle 数据库 (18c) 中的数据创建报告。其中一个报告在返回大量数据时遇到问题。供应商通知我,我的 SQL 是“不合格的”。他们说像这样的 SQL......
select a.Name
, a.Descr
from tblA a
inner join tblB b on b.aID = a.aID
inner join tblC c on c.bID = b.bID
where sysdate between c.StartDate and c.EndDate
and c.Name in ('X', 'Y', 'Z')
...错了,而这......
select a.Name
, a.Descr
from tblA a
, tblB b
where b.aID = a.aID
and b.bID in (
select c.bID
from tblC c
where sysdate between c.StartDate and c.EndDate
and c.Name in ('X', 'Y', 'Z')
)
...是正确的。
这是一个戏剧性的例子。原始查询很大,但这基本上是我被告知导致问题的差异。
我很困惑,因为我没有看到任何有意义的区别。
- 这些查询是否会产生不同的结果?
- “in (subquery)”语法可以避免重复吗?
INNER JOIN
- 使用子查询如何增加任何值?会更快吗?
- 大约 2 年前,“逗号”样式的连接不是被弃用了吗?
答:
首先,我想这是一个错别字,应该是.b.aID = b.aID
b.aID = a.aID
然后,看到他们希望你使用逗号连接()是很奇怪的,就像在1980年代所做的那样。这是一个过时的语法,现在不应该使用。from tblA a, tblB b
但是,是的,原始查询可能会导致重复的结果行。如果只想从 tblA 中选择数据,则仅从 tblA 中选择并将条件放在子句中。我想这就是他们通过将 tblC 放入子句中来尝试做的事情。一个好主意,它应该看起来像这样:WHERE
IN
SELECT a.name, a.descr
FROM tbla a
WHERE a.aid IN
(
SELECT b.aid
FROM tblb b
INNER JOIN tblc c ON c.bid = b.bid
WHERE SYSDATE BETWEEN c.startdate AND c.enddate
AND c.name IN ('X', 'Y', 'Z')
);
回答您的问题:
- 这些查询是否会产生不同的结果?是的。
- INNER JOIN是否会导致“in (subquery)”语法避免的重复?是的。
- 使用子查询如何增加任何值?会更快吗?是的,速度更快,而且不会产生重复项。
- 大约 2 年前,“逗号”样式的连接不是被弃用了吗?实际上,即使在三十年前,甲骨文也晚了十年才采用这种语法。所以,是的。
生产线
WHERE SYSDATE BETWEEN c.startdate AND c.enddate
顺便说一句,看起来有点可疑。startdate 和 enddate 可能是日期,同时还包含时间。因此,我们希望 SYSDATE 在日期范围内,但根据 enddate 是包含还是排除,这应该是SYSDATE
WHERE c.startdate <= SYSDATE AND c.enddate > SYSDATE
或
WHERE c.startdate <= SYSDATE AND c.enddate > SYSDATE - INTERVAL '1' DAY
为了不让接下来的午夜被包括在内。
评论
我认为也许供应商并没有试图让 Oracle 原生与 ANSI 连接语法成为问题。我认为他们建议的重写表明您的联接不恰当地增加了行数(如果在给定日期内不唯一),并建议了子查询,以便它不会使您的行成倍增加。还有其他方法可以做到这一点,但他们的建议很好。换句话说,对于您的问题:tblC
c.bid
tblC
INNER JOIN是否会导致“in (subquery)”语法重复 避免?
是的。这可能就是重点。或者,他们可能正在尝试调整您的查询,并提供他们认为更快的方法。它可能是也可能不是,但子查询是重点,而不是连接语法。
说到原生的 Oracle 连接语法,与这个论坛上大多数人一直说的相反,它没有错。它从未被弃用,并且仍然有大量仍在使用中。这很大程度上取决于风格和个人使用。这可能是供应商最熟悉的,可能不是他们说你应该改变的。选择您喜欢的任何语法并使用它。
评论
WHERE
FROM
LEFT OUTER JOIN
RIGHT OUTER JOIN
INNER JOIN
评论
sysdate
SYSDATE
SYSDATE
GETDATE()
SQL Server
JOIN