SQL查询where子句如果没有匹配记录则省略
Posted
技术标签:
【中文标题】SQL查询where子句如果没有匹配记录则省略【英文标题】:SQL Query where clause omit if no matching records 【发布时间】:2020-12-04 04:09:58 【问题描述】:我目前正在处理一个从具有 20 列的复杂 sql 视图中读取数据的 sql 查询。 我应该使用 8 where 条件读取数据。在这 8 个条件中,有一个条件是可选的。意思是,如果没有满足所有这 8 个条件的匹配记录,则省略可选的 where 条件并返回结果。
下面是一个进一步解释的例子::
表格:: EMPLOYEE_DETAILS
EMP_NO EMP_NAME EMP_DEPT_NO PREF_LANGUAGE LOCATION
------ -------- ----------- ------------- ---------
1 Name1 101 ENGLISH USA
2 Name2 102 SPANISH SPAIN
3 Name3 103 ENGLISH USA
4 Name4 102 ITALIAN ITALY
5 Name5 103 ENGLISH USA
6 Name6 103 ITALIAN ITALY
查询:
SELECT * FROM EMPLOYEE_DETAILS
WHERE EMP_DEPT_NO = 103 AND LOCATION ='USA' AND PREF_LANGUAGE = 'SPANISH'
在此示例 sql 查询中,PREF_LANGUAGE 条件是可选的。 如果有匹配所有三个条件的记录,则只返回那些匹配的记录。 由于上表没有满足所有三个条件的记录,因此查询应省略可选条件(即 PREF_LANGUAGE),并返回满足其余两个必需条件的记录。
非常感谢任何帮助。
谢谢
【问题讨论】:
【参考方案1】:我想我会像这样对查询进行调整:
WITH cte AS (
SELECT ed.*,
SUM(CASE WHEN PREF_LANGUAGE = 'SPANISH' THEN 1 ELSE 0 END) OVER () as NUM_PREF_SPANISH
FROM EMPLOYEE_DETAILS ed
WHERE EMP_DEPT_NO = 103 AND LOCATION = 'USA'
)
SELECT *
FROM cte
WHERE PREF_LANGUAGE = 'SPANISH' OR
NUM_PREF_LANGUAGE = 0;
这样表述的原因是 Oracle 并不总是实现 CTE。这保证了 CTE 仅被引用一次,因此优化器不会决定多次运行您的复杂代码。
您也可以使用WITH TIES
技巧在最新版本的 Oracle 中执行此操作:
SELECT ed.*,
FROM EMPLOYEE_DETAILS ed
WHERE EMP_DEPT_NO = 103 AND LOCATION = 'USA'
ORDER BY(CASE WHEN PREF_LANGUAGE = 'SPANISH' THEN 1 ELSE 2 END)
FETCH FIRST 1 ROW WITH TIES;
【讨论】:
【参考方案2】:我会在这里使用存在逻辑:
WITH cte AS (
SELECT *
FROM EMPLOYEE_DETAILS
WHERE
EMP_DEPT_NO = 103 AND
LOCATION = 'USA'
)
SELECT *
FROM cte
WHERE PREF_LANGUAGE = 'SPANISH' OR
NOT EXISTS (SELECT 1 FROM cte
WHERE PREF_LANGUAGE = 'SPANISH')
在简单的英语中,上述查询将返回部门为 103、位置为美国以及首选语言为西班牙语的记录或没有记录具有此首选语言。在后一种情况下,无论首选语言如何,它都会返回记录。
【讨论】:
谢谢蒂姆,但我提到的那个查询是一个例子。我目前在生产中工作的 sql 查询比我在示例中显示的要大得多。您的建议使我的 sql 查询更加难看,因为我必须复制/粘贴几乎整个 30 行 sql 查询。请提出仅适用于该可选 where 条件的内容。【参考方案3】:你可以使用DENSE_RANK
解析函数如下:
SELECT * FROM
(SELECT T.*,
DENSE_RANK()
OVER (ORDER BY CASE WHEN PREF_LANGUAGE = 'SPANISH' THEN 1 ELSE 2 END) AS RN
FROM EMPLOYEE_DETAILS T
WHERE EMP_DEPT_NO = 103
AND LOCATION ='USA')
WHERE RN = 1
【讨论】:
以上是关于SQL查询where子句如果没有匹配记录则省略的主要内容,如果未能解决你的问题,请参考以下文章