如果满足 COUNT 条件,我可以应用 WHERE 子句吗?

Posted

技术标签:

【中文标题】如果满足 COUNT 条件,我可以应用 WHERE 子句吗?【英文标题】:Can I apply a WHERE clause if COUNT condition is met? 【发布时间】:2020-06-07 15:45:53 【问题描述】:

我很难尝试添加一个 WHERE 子句,该子句仅在有其他行返回同一列的数据时过滤列中的 null 值。

如果所有行都有该列的null值,则保留所有行。

如果任何行包含该列的数据,则删除具有空值的行并仅保留包含数据的行。

我正在开发一个 Oracle 数据库。

在我的 SELECT 语句中,我目前正在使用 LEFT JOIN表 B 中提取数据,即使列 B.info 的值为空。

实际查询如下:

SELECT A.id as A_ID, A.name as A_NAME, 
B.id as B_ID, B.name as B_NAME, B.info as B_INFO
FROM A
LEFT JOIN B ON B.id = A.id_B
WHERE A.filename = 'file1.txt' 

我正在从事的业务中有两种可能的情况:

    对于给定的“文件名”,查询返回一些行,其中一些行的B.info 列为空值,而另一些行的B.info 列中填充了数据。我希望查询返回带有B.info != null 的行。

场景 1 - 实际输出:

+-------+--------+------+--------+-----------+
| A_ID  | A_NAME | B_ID | B_NAME | B_INFO    |
+-------+--------+------+--------+-----------+
| 1     | John   | null | null   | null      |
+-------+--------+------+--------+-----------+
| 2     | John   | 3    | Julia  | Age is 35 |
+-------+--------+------+--------+-----------+
| 3     | John   | null | null   | null      |
+-------+--------+------+--------+-----------+

场景 1 - 所需输出:

+-------+--------+------+--------+-----------+
| A_ID  | A_NAME | B_ID | B_NAME | B_INFO    |
+-------+--------+------+--------+-----------+
| 2     | John   | 3    | Julia  | Age is 35 |
+-------+--------+------+--------+-----------+
    对于给定的“文件名”,查询返回具有B.info 列和null 值的所有行。 我希望查询继续返回这些行。

场景 2 - 实际输出 = 期望输出:

+-------+--------+------+--------+--------+
| A_ID  | A_NAME | B_ID | B_NAME | B_INFO |
+-------+--------+------+--------+--------+
| 1     | Mark   | null | null   | null   |
+-------+--------+------+--------+--------+
| 2     | Mark   | null | null   | null   |
+-------+--------+------+--------+--------+
| 3     | Mark   | null | null   | null   |
+-------+--------+------+--------+--------+

我尝试在 where 子句中添加条件 B.info is not null,但是,虽然它返回了场景 1 的所需输出,但场景 2 的输出没有返回任何行:

SELECT A.id as A_ID, A.name as A_NAME, 
B.id as B_ID, B.name as B_NAME, B.info as B_INFO
FROM A
LEFT JOIN B ON B.id = A.id_B
WHERE A.filename = 'file1.txt' 
AND B.info is not null

场景 1 - 输出

+-------+--------+------+--------+-----------+
| A_ID  | A_NAME | B_ID | B_NAME | B_INFO    |
+-------+--------+------+--------+-----------+
| 2     | John   | 3    | Julia  | Age is 35 |
+-------+--------+------+--------+-----------+

场景 2 - 输出

+-------+--------+------+--------+--------+
| A_ID  | A_NAME | B_ID | B_NAME | B_INFO |
+-------+--------+------+--------+--------+
+-------+--------+------+--------+--------+

我也尝试在 WHERE 子句中添加 CASE,但它会引发错误 (ORA-00934: group function is not allowed here)

SELECT A.id as A_ID, A.name as A_NAME, 
B.id as B_ID, B.name as B_NAME, B.info as B_INFO
FROM A
LEFT JOIN B ON B.id = A.id_B
WHERE A.filename = 'file1.txt' 
AND B.info = CASE WHEN count(B.info) > 0 THEN null
    ELSE B.info
    END

很抱歉,我无法将真实示例用于保密问题。我希望我的例子足够清楚。我将不胜感激!

【问题讨论】:

【参考方案1】:

计算所有行和可为空的行。使用分析计数,因为您需要详细信息。如果两个计数相等,则仅显示包含数据的行或空行:

select id, a_name, b_name, info
  from (
    select a.id, b.id b_id, a.name a_name, b.name b_name, b.info, 
           count(case when b.id is null then 1 end) over (partition by a.filename) c1,
           count(1) over (partition by a.filename) c2
      from a left join b on a.id = b.id )
  where b_id is not null or c1 = c2

demo

【讨论】:

【参考方案2】:

您可以将此问题视为排名问题:您只想显示最佳行,非空行被认为比空行“更好”。

可以使用适当的 ORDER BY 子句来实现排名。从 Oracle 12c 开始:

select
  a.id as a_id, a.name as a_name, 
  b.id as b_id, b.name as b_name, b.info as b_info
from a
left join b on b.id = a.id_b
where a.filename = 'file1.txt'
order by case when b.id is null then 2 else 1 end
fetch first rows with ties;

在旧版本中:

select a_id, a_name, b_id, b_name, b_info
from
(
  select
    a.id as a_id, a.name as a_name, 
    b.id as b_id, b.name as b_name, b.info as b_info,
    rank() over (order by case when b.id is null then 2 else 1 end) as rnk
  from a
  left join b on b.id = a.id_b
  where a.filename = 'file1.txt'
)
where rnk = 1;

【讨论】:

以上是关于如果满足 COUNT 条件,我可以应用 WHERE 子句吗?的主要内容,如果未能解决你的问题,请参考以下文章

thinkphp自带的分页 查询数据时怎么使用where条件

如果在 SSMS 中不满足条件,where 子句不返回任何内容

SQL 语句 join where 如果一个条件不满足,则执行另一个条件

如果满足条件,SQL Count 函数计算所有行

SQL:如果两个条件都满足而不是在多个where中单独排除,如何仅排除条件?

如何知道 WHERE 语句中有多少条件满足其条件?