SQL在select子查询中只返回一行或null

SQL在select子查询中只返回一行或null,sql,oracle,subquery,Sql,Oracle,Subquery,在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; 谢谢 除了一个案例解决方案或将内联子查询重写为外部联接之外,如果

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

谢谢

除了一个
案例
解决方案或将内联子查询重写为外部联接之外,如果您可以在
W
列上应用聚合函数(
MIN
MAX
):

SELECT
    X, Y, Z, (SELECT W FROM TABLE2 WHERE X = TABLE1.X HAVING COUNT(*) = 1) 
FROM 
    TABLE1;
SELECT X,
  Y,
  Z,
  (SELECT MIN(W) FROM TABLE2 WHERE X = TABLE1.X HAVING COUNT(*) = 1) AS W
FROM TABLE1;

换一种方式怎么样?带有子查询的简单左外部联接应该满足您的要求:

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;
这将只返回正好有一个X实例的项,并在适当时将其返回到表中(将非匹配项保留为NULL)


这也是符合ANSI标准的,因此性能相当好。

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

在这里使用PlantTheIdea提到的subselect没有必要,也不是一个好主意,因为有两个原因

解释:

子选择是指:

主选择结果集的每行一个选择。i、 e.如果您得到1000行,那么您的数据库系统中也会得到1000(小)select STATEMT(忽略优化器)

和(!)

通过子选择,您很有可能隐藏(或覆盖)大量数据库或选择问题。这意味着:您只需要一行(空)或一行(精确)(两者都可以通过[left outer]联接轻松解析)。如果您的子选择中有多个错误,那么SQL错误会指出这一点

“HAVING COUNT(X)=1”当然是正确的,但有一个小(或不小)问题,那就是:“为什么有多行的计数?”

我花了好几个小时找一个这样的工作,结果只是“如果你真的确定的话就不要做…”

我认为这与这样的“拥有”相反

 ...
 HAVING date=max(date) -- depends on sql dialect


在我的最后一个例子中,我想再次指出:如果这里有多行(都是从今天开始的),那么您就有一个DB问题-您可以使用时间戳,例如,您可以使用case语句。。您尚未在subquery.derp中选择
X
!谢谢你。我也意识到没有必要分组,因为每个实例的返回值总是正好是1。很抱歉,这不会按原样运行。您需要聚合或一些窗口/分析函数wizadry。您不能只使用
在.derp周围包含
子句的
选择x,w
。。。这就是我没有测试的结果,哈哈<代码>拥有
需要一个
分组依据
@plantheldea这几乎可以工作,除了我得到额外的行,而不是与表1相同的行数。我尝试了其他类型的联接,但它们返回的行数都比表1略多或略少。这样做需要group by,当我执行group by时,会出现一个错误,指出“单行子查询返回多行”。可能值得一提的是,子查询的where子句有多个部分。表1和表2有几个字段是匹配行所必需的,而不仅仅是W。这不需要
分组依据。
where date = select max(date) from same_table