用于选择行的 Where 语句层次结构

Posted

技术标签:

【中文标题】用于选择行的 Where 语句层次结构【英文标题】:Where statement Hierarchy for Selecting rows 【发布时间】:2019-03-08 19:13:39 【问题描述】:

我有一个表,其中包含一个名为 ReportTypeId 的列。我想选择 ReportTypeId = 1 的行,但如果不存在此行,那么我想要 ReportTypeId = 2。我正在尝试使用 WHEN EXISTS,但我无法弄清楚如何选择多于一列。我想编写一个看起来像这样的查询:

SELECT CASE 
    WHEN EXISTS (SELECT PerformanceReport FROM ReportData
                    WHERE (ReportId = 79 and ReportTypeId = 1))

        THEN (select * from ReferenceData               
                where ReportTypeId = 1)

        ELSE (select * from ReferenceData
                where ReportTypeId = 2)
    END

但是因为我试图返回不止一列,所以它不起作用。有没有办法根据数据是否存在来创建基于 WHERE 语句的查询?

【问题讨论】:

【参考方案1】:

如果RecordTypeId可以订购**,那么你可以使用以下

SELECT PerformanceReport 
FROM ReferenceData
WHERE ReportTypeId = (
      SELECT MIN(ReportTypeId) 
      FROM ReportData 
      WHERE ReportTypeId IN (1, 2)
        AND ReportId = 79
)

** 按顺序,我的意思是 MIN 聚合函数将返回预期结果。但是,对于整数,这是有道理的,如果您的报告类型 id 是文本 uuid,那么 MIN 仍然可以工作,但不会给您预期的结果,因为它会按词法顺序返回最小 id。

【讨论】:

这对我的情况很有用,但我可以看到,如果 ReportTypeId = 2 成为优先于 1 的优先级,但不像 3 (2 > 1 > 3) 那样导入,那么我猜我运气不好?...好吧,我想我可以创建一个临时表来分配重要性等级,所以实际上是的,我真的很喜欢这个解决方案,谢谢! @Mwspencer 。 . .当这个答案似乎没有从正确的表格中选择时,我对如何接受这个答案感到困惑。 @GordonLinoff,我认为这不仅仅是我接受的硬代码的想法。由于我的实际用户案例比我的问题要复杂一些,因此这个答案有助于创建最直接的解决方案。我承认我没有测试过性能,因为这对我的具体情况并不重要。所有答案都给出了正确的输出,但这个用最少的代码。【参考方案2】:

您可以使用以下解决方案:

SELECT * 
FROM ReferenceData
WHERE (
    ReportTypeId = 1 
    AND EXISTS (SELECT * FROM ReportData WHERE ReportTypeId = 1 AND ReportId = 79)
) OR (
    ReportTypeId = 2
    AND NOT EXISTS (SELECT * FROM ReportData WHERE ReportTypeId = 1 AND ReportId = 79)
)

您可以使用 JOIN 优化此功能:

SELECT ReferenceData.* 
FROM ReferenceData JOIN (
    SELECT EXISTS (SELECT * FROM ReportData WHERE ReportTypeId = 1 AND ReportId = 79) AS state
) isAvailable
WHERE (
    ReportTypeId = 1 AND isAvailable.state = 1
) OR (
    ReportTypeId = 2 AND isAvailable.state = 0
)

您可以使用JOIN:添加多个检查:

SELECT ReferenceData.* 
FROM ReferenceData JOIN (
    SELECT EXISTS (SELECT * FROM ReportData WHERE ReportTypeId = 1 AND ReportId = 79) AS state
) avail1 JOIN (
    SELECT EXISTS (SELECT * FROM ReportData WHERE ReportTypeId = 2 AND ReportId = 79) AS state
) avail2 JOIN (
    SELECT EXISTS (SELECT * FROM ReportData WHERE ReportTypeId = 3 AND ReportId = 79) AS state
) avail3
WHERE (
    ReportTypeId = 1 AND avail1.state = 1
) OR (
    ReportTypeId = 2 AND avail1.state = 0 AND avail2.state = 1
) OR (
    ReportTypeId = 3 AND avail1.state = 0 AND avail2.state = 0 AND avail3.state = 1
) OR (
    ReportTypeId = 4 AND avail1.state = 0 AND avail2.state = 0 AND avail3.state = 0
)

demo on dbfiddle.uk

【讨论】:

【参考方案3】:

你似乎想要:

SELECT refd.* 
FROM ReferenceData refd
WHERE (refd.ReportType = 1 AND 
       EXISTS (SELECT 1
               FROM ReportData repd
               WHERE repd.ReportId IN (1, 79)
              )
      ) OR
      (refd.ReportType = 2 AND 
       EXISTS (SELECT 1
               FROM ReportData repd
               WHERE repd.ReportId NOT IN (1, 79)
              )
      )

【讨论】:

这似乎是一个干净的解决方案,但我不确定为什么使用 AND。如果 ReportTypeId = 1,我想选择报告,否则,我想要 ReportType = 2,但我不想要两种报告类型。我也不确定我们为什么要寻找 repd.ReportId IN (1, 79) 而不仅仅是 repd.ReportId = 79。 @Mwspencer 。 . .谢谢你。那是一个错字。

以上是关于用于选择行的 Where 语句层次结构的主要内容,如果未能解决你的问题,请参考以下文章

SSAS MDX WHERE 子句语法 - 从同一层次结构中过滤多个值

Go流程结构(for)

SQL中where 1=1和0=1的作用

用于搜索资源的 RESTFul 平面层次结构与动态层次结构

面试准备 Java 异常类层次结构

用于构建视图层次结构的 viewWillAppear 与 loadView