假设我有一个包含2列的表t
:
a int
b int
我可以进行如下查询:
select b
from t
where b > a
and a in(1,2,3)
order by b
其中1,2,3
来自外部。
显然,查询不能返回任何行。在这种情况下,我想选择所有内容,就好像查询没有and a in(1,2,3)
部分一样。也就是说,我喜欢:
if exists (
select b
from t
where b > a
and a in(1,2,3)
)
select b
from t
where b > a
and a in(1,2,3)
order by b
else
select b
from t
where b > a
order by b
有没有办法做到这一点:
答案 0 :(得分:0)
使用带有子查询的NOT EXISTS来确定条件是否存在
SELECT b
FROM
t
WHERE
b > a
AND (
NOT EXISTS (SELECT 1 FROM @Table WHERE a IN (1,2,3))
OR a IN (1,2,3)
)
ORDER BY
b
这是有效的原因是因为如果条件存在则OR语句将包含行,如果条件不存在则NOT EXISTS将包括所有行。
或使用公用表表达式和带有条件聚合的窗口函数。
WITH cte AS (
SELECT
b
,CASE WHEN a IN (1,2,3) THEN 1 ELSE 0 END as MeetsCondition
,COUNT(CASE WHEN a IN (1,2,3) THEN a END) OVER () as ConditionCount
FROM
t
)
SELECT
b
FROM
cte
WHERE
(ConditionCount > 0 AND MeetsCondition = 1)
OR (ConditionCount = 0)
ORDER BY
b
答案 1 :(得分:-1)
我发现它有点"丑陋"。也许最好在临时表中实现查询的输出,然后根据临时表中的count
执行第一次或第二次查询(这限制访问原始表3次到2次,你将能够为条件添加一些标志为您的条件不重复它)。除此之外,请阅读以下内容。 。
但是,请记住,EXISTS
查询应该执行得非常快。它会停止是否找到满足条件的行。
您可以使用UNION ALL
将约束查询的结果集与a
列上没有约束的完整查询相结合,然后根据使用CASE
语句的第一个查询的输出决定要显示的内容
CASE语句的工作原理:当找到查询的约束部分中的任何行时,从约束查询返回结果集,否则返回省略约束的所有内容。
如果您的数据库支持使用CTE
,请使用此解决方案:
with tmp_data as (
select *
from (
select 'constraint' as type, b
from t
where b > a
and a in (1,2,3) -- here goes your constraint
union all
select 'full query' as type, b
from t
where b > a
) foo
)
SELECT b
FROM tmp_data
WHERE
CASE WHEN (select count(*) from tmp_data where type = 'constraint') > 0
THEN type = 'constraint'
ELSE type = 'full query'
END
;