SQL查询时的复杂情况

时间:2019-09-10 08:02:07

标签: sql oracle

我有如下的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')

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

我也知道我可以使用regexp而不是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

1 个答案:

答案 0 :(得分:0)

查询始终必须返回相同数量的列。我所看到的与您建议的最接近的是将两个查询的结果与伪列合并在一起,因此投影始终是相同的。并使用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