【问题标题】:Complex CASE WHEN SQL query复杂的 CASE WHEN SQL 查询
【发布时间】:2019-09-10 18:19:51
【问题描述】:

我有如下 SQL 查询:

SELECT COUNT(*) FROM table t
WHERE LENGTH(TRIM(TRANSLATE(t.field, 'BWE123', ' '))) > 0
OR SUBSTR(t.field, 0, 1) IN ('0', '1')

上面的查询检查表中的字段不包含“BWE123”以外的值,以及第一个字符是否不是 0 或 1。 如果该字段接受除允许之外的其他字符,则查询返回无效记录数。 我想扩展上面的查询:

如果 count = 0 下面的查询应该开始:

SELECT count(*) FROM table 

如果 count > 0 下面的查询应该开始:

SELECT * FROM table t
WHERE LENGTH(TRIM(TRANSLATE(t.field, 'BWE123', ' '))) > 0
OR SUBSTR(t.field, 0, 1) IN ('0', '1')

有人知道如何创建这种查询吗?

我也知道我可以使用正则表达式而不是 LENGTH - TRIM - TRANSLATE,我稍后会更改它。

问候


抱歉,我会从头开始解释我想要实现的目标。 目前我有这样的疑问:

SELECT 'MY_TABLE' as TABLE, COUNT(*) AS ERROR_COUNT, 'mt.field1' AS COLUMN FROM my_table mt
WHERE LENGTH(TRIM(TRANSLATE(mt.field1, '0123456789', ' '))) > 0
OR mt.field1 IS NULL
UNION
SELECT 'MY_TABLE' as TABLE, COUNT(*) AS ERROR_COUNT, 'mt.field2' AS COLUMN FROM my_table mt
WHERE LENGTH(TRIM(TRANSLATE(mt.field2, '0123456789.-*', ' '))) > 0
OR mt.field2 IS NULL;

它们的执行结果如下表(假设表中的field1值为'1234',所以我们有0个错误, field2 的值为 'a1234' 所以我们有错误)

TABLE       ERROR_COUNT     COLUMN 
-----       -----------     ------
MY_TABLE    0               mt.field1
MY_TABLE    1               mt.field2

我以我必须测试的最小表为例,我也有包含 200 列或更多列的表。 我想要达到的目标: 如果我们有错误(对于 field2),我想创建并运行返回下表的附加查询(在第二个查询结果选项卡中):

TABLE       INVALID_CHAR    COLUMN 
-----       -----------     ------
MY_TABLE    a               mt.field2

示例表(IP):

ID      IP_NO           PHONE   
-----       --------        ---------
101     192.205.230.70      +535950331
10#     192.205a.230.70     +672819233
103     192.205.230.70      +991873112
10!     192.205.230.70      +764616233

查询:

SELECT 'IP' as TABLE, COUNT(*) AS ERROR_COUNT, 'mt.ID' AS COLUMN FROM ip
WHERE LENGTH(TRIM(TRANSLATE(ip.id, '0123456789', ' '))) > 0
OR ip.id IS NULL
UNION
SELECT 'IP' as TABLE, COUNT(*) AS ERROR_COUNT, 'mt.ip_no' AS COLUMN FROM ip
WHERE LENGTH(TRIM(TRANSLATE(ip.ip_no, '0123456789.', ' '))) > 0
OR ip.ip_no IS NULL
UNION
SELECT 'IP' as TABLE, COUNT(*) AS ERROR_COUNT, 'mt.phone' AS COLUMN FROM ip
WHERE LENGTH(TRIM(TRANSLATE(ip.phone, '+0123456789', ' '))) > 0
OR ip.phone IS NULL

结果表:

TABLE       ERROR_COUNT     COLUMN 
-----       -----------     ------
IP          2               mt.id
IP          1               mt.ip_no
IP          0               mt.phone

我要创建的表:

TABLE       INVALID_CHAR    COLUMN 
-----       -----------     ------
IP          #               mt.id
IP          !               mt.id
IP          a               mt.ip_no

【问题讨论】:

  • 您的查询不能返回单个(数字、计数)列多个列。列数必须固定。无论如何,这将如何解释结果?您可以将计数附加为额外的列并将结果合并,但不清楚您想要发生什么。
  • 其实此时我们可以跳过 count = 0 的条件。在第二个查询中,我想验证如果第一个查询中的 count 大于 0 会出现哪些无效字符
  • 如果您不想查看计数,那么您的最终查询已经只列出了这些行?

标签: sql oracle


【解决方案1】:

查询总是必须返回相同数量的列。我能看到的最接近您的建议是将两个查询的结果与虚拟列结合在一起,因此投影始终相同;并使用 CTE 来减少重复。比如:

WITH cte as (
  SELECT t.field,
    COUNT(*) OVER () as total_count,
    CASE WHEN LENGTH(TRIM(TRANSLATE(t.field, 'BWE123', ' '))) > 0
              OR SUBSTR(t.field, 0, 1) IN ('0', '1')
         THEN 1
         ELSE 0
    END as is_invalid,
    COUNT(CASE WHEN LENGTH(TRIM(TRANSLATE(t.field, 'BWE123', ' '))) > 0
                    OR SUBSTR(t.field, 0, 1) IN ('0', '1')
               THEN 1
          END) OVER () as invalid_count
  FROM your_table t
)
SELECT cte.field, null as total_count
FROM cte
WHERE is_invalid = 1
UNION ALL
SELECT null, max(total_count)
FROM cte
WHERE invalid_count = 0

只有联合的一个分支可以找到任何一组基础数据的任何结果。你要么得到如下结果:

FIELD  TOTAL_COUNT
------ -----------
0                 
1BWE23            

or

FIELD  TOTAL_COUNT
------ -----------
                 4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-30
    • 2017-08-15
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    相关资源
    最近更新 更多