如果满足 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 如果一个条件不满足,则执行另一个条件