在 Oracle 中,是否可以在 select 语句中有一个子查询,如果子查询恰好返回一行,则返回一列,如果子查询没有返回或返回多于一行,则返回 null?
例子:
SELECT X,
Y,
Z,
(SELECT W FROM TABLE2 WHERE X = TABLE1.X) /* but return null if 0 or more than 1 rows is returned */
FROM TABLE1;
谢谢!
以不同的方式进行如何?带有子查询的简单 LEFT OUTER JOIN 应该可以满足您的要求:
SELECT T1.X
,T1.Y
,T1.Z
,T2.W
FROM TABLE1 AS T1
LEFT OUTER JOIN (
SELECT X
,W
FROM TABLE2
GROUP BY X,W
HAVING COUNT(X) = 1
) AS T2 ON T2.X = T1.X;
这只会返回恰好有 1 个 X 实例的项目,并在适当的时候将其 LEFT OUTER JOIN 返回到表中(将不匹配项保留为 NULL)。
这也符合 ANSI 标准,因此性能非常好。
除了CASE
解决方案或将内联子查询重写为外部联接之外,如果您可以在列上应用聚合函数(MIN
或MAX
) ,这将起作用W
:
SELECT X,
Y,
Z,
(SELECT MIN(W) FROM TABLE2 WHERE X = TABLE1.X HAVING COUNT(*) = 1) AS W
FROM TABLE1;
我的回答是:不要使用子选择(除非你确定......)
没有必要也不是一个好主意在这里使用子选择作为 PlantTheIdea 提到的,因为有两件事
解释:
子选择意味着:
对主选择结果集的每一行进行一次选择。即如果你得到 1000 行,你也会在你的数据库系统中得到 1000 个(小)选择语句(这里忽略优化器)
和(!)
使用子选择,您有很好的机会隐藏(或覆盖)繁重的数据库或选择问题。这意味着:您只期望没有(NULL)或一个(确切)行(两者都可以通过 [left outer] 连接轻松解决)。如果您的子选择中有多个有问题,则 SQL 错误会指出
“HAVING COUNT(X) = 1”当然是正确的,有小(或不小)的问题,那就是:“为什么计数不止一行?”
我花了好几个小时寻找这样的解决方法,结果却是“如果你真的确定就不要这样做……”
我看到这与这样的“拥有”相反
...
HAVING date=max(date) -- depends on sql dialect
或者
where date = select max(date) from same_table
在我的最后一个示例中,我再次想指出:如果您到达这里不止一行(都从今天开始;。)您遇到了数据库问题 - 例如,您应该使用时间戳
SELECT
X, Y, Z, (SELECT W FROM TABLE2 WHERE X = TABLE1.X HAVING COUNT(*) = 1)
FROM
TABLE1;