首页 > 解决方案 > 如何扩展 SQL 语句以包含多个条件?

问题描述

我这里有这个 SQL 语句

SELECT COUNT(*) AS ACB
FROM APPL
WHERE CPTR_APPL_ID LIKE '%(' AND APPL.CRE_TS >= to_date('20190801','yyyymmdd') 
    AND APPL.CRE_TS <  to_date('20190802','yyyymmdd')

现在,这可以找到数据库中在正确日期以“(”符号结尾的所有应用程序。是否可以扩展这个单一查询,以便它与我的数据库中以 A 或 B 或 C 或其他任何结尾的其他应用程序一起工作?他们都需要在同一个日期。我只需要计算每个应用程序类型并将其放在具有我选择的名称的列中。

我应该在 where 部分使用“OR”吗?

标签: sqloracle

解决方案


几种方法(实际上有很多方法,但这些相对容易理解

选择计数:

WITH cte AS
(
  SELECT CPTR_APPL_ID as typ
  FROM APPL
  WHERE APPL.CRE_TS >= DATE '2019-08-01' AND 
  APPL.CRE_TS < DATE '2019-08-02'
)
SELECT
  (SELECT COUNT(*) FROM cte WHERE typ LIKE '%A') as count_a,
  (SELECT COUNT(*) FROM cte WHERE typ LIKE '%B') as count_b,
  ...
FROM dual

我从来都不喜欢“在选择列表中选择”查询。根据 oracle 需要扫描表多少次来进行计数,这个性能可能会很差。您希望 cte 将作为第一步进行处理,这是一个减少的结果集,然后将被计算在内,但您的优化器可能会以非常不同的方式计划事情

普通的 ISO SQL 数据透视方法:

  SELECT 
    SUM(CASE WHEN CPTR_APPL_ID LIKE '%A' THEN 1 END) as COUNT_A,
    SUM(CASE WHEN CPTR_APPL_ID LIKE '%B' THEN 1 END) as COUNT_B,
    ...
  FROM APPL
  WHERE APPL.CRE_TS >= DATE '2019-08-01' AND 
  APPL.CRE_TS < DATE '2019-08-02'

我首选的旋转方法适用于所有数据库。基本上,当您的数据变为空值或 1 时,取决于它是否以 A 结尾(或 B 等),然后 SUM 将所有 1 相加,给出一个计数。Sum 忽略空值。可以通过不求和的列来扩展,只要这些列出现在 group by 中。性能应该不错,因为它可以在从 WHERE 过滤器返回的数据上一次性完成

枢轴语法:

SELECT * FROM
(
  SELECT SUBSTR(CPTR_APPL_ID, -1) as typ
  FROM APPL
  WHERE APPL.CRE_TS >= DATE '2019-08-01' AND 
  APPL.CRE_TS < DATE '2019-08-02'
)
PIVOT 
(
  COUNT(typ)
  FOR typ
  IN ('A', 'B', ...) --this could be a query if you wanted dynamic
)

缺点是它是专有的,但它可以是动态的或固定的列值。有些人真的很喜欢这个并记住语法,其他人(我)总是要查找它

如果这些查询中的任何一个有错别字,请告诉我——它们是在没有经过任何测试的情况下编写的。他们都需要对您想要的特定代码进行一些调整,希望您能看到所有这些模式并扩展它


推荐阅读