2

在 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;

谢谢!

4

4 回答 4

6

以不同的方式进行如何?带有子查询的简单 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 标准,因此性能非常好。

于 2013-11-05T20:41:29.150 回答
1

除了CASE解决方案或将内联子查询重写为外部联接之外,如果您可以在列上应用聚合函数(MINMAX) ,这将起作用W

SELECT X,
  Y,
  Z,
  (SELECT MIN(W) FROM TABLE2 WHERE X = TABLE1.X HAVING COUNT(*) = 1) AS W
FROM TABLE1;
于 2013-11-05T20:35:21.877 回答
0

我的回答是:不要使用子选择(除非你确定......)

没有必要也不是一个好主意在这里使用子选择作为 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

在我的最后一个示例中,我再次想指出:如果您到达这里不止一行(都从今天开始;。)您遇到了数据库问题 - 例如,您应该使用时间戳

于 2013-11-05T22:15:07.810 回答
0
SELECT
    X, Y, Z, (SELECT W FROM TABLE2 WHERE X = TABLE1.X HAVING COUNT(*) = 1) 
FROM 
    TABLE1;
于 2013-11-05T20:31:16.737 回答