【问题标题】:SQL Filter items from a listSQL 筛选列表中的项目
【发布时间】:2011-05-04 06:44:42
【问题描述】:

我需要过滤掉 SQL 表中的行,这些行在指定值列表中的一列中具有值。简化后的表格如下所示:(抱歉格式错误,以前从未在此处发布过)

Error Codes     | Other Column 1 | Other Column 2 ...

--------------------------------------------------
F010,F123,F345, |  ......        | .....

F231,FC85,F904, |  ......        | .....

FC432,F0425,NA, |  ......        | .....

 ....

我首先拆分错误代码列以获取 3 个错误代码中的每一个,这是一个逗号分隔的值字符串。然后我需要过滤掉给定列表中包含所有三个错误代码的行,例如('F010'、'FC542'、'FB943')。我在 Teradata 数据库上运行它,这是查询的一部分,但似乎没有过滤掉列表中的所有组合:

SELECT ... , 

CASE
WHEN ( substr(a.error_code, 1, position(',' in a.error_code)-1) in ('F010', 'FC542', 'FB012' 'FB943', 'NA')

AND substr(a.error_code,
              position(',' in a.error_code)+1, 
              position(',' in substr(a.error_code,  position(',' in a.error_code)+1, Characters(a.error_code)-position(',' in a.error_code)))-1) in ('F010', 'FC542', 'FB012' 'FB943', 'NA')

AND substr(a.error_code,
          position(',' in a.error_code) + position(',' in substr(a.error_code,    position(',' in a.error_code)+1, Characters(a.error_code)-position(',' in a.error_code)))+1,
          Characters(a.error_code)-(position(',' in a.error_code) + position(',' in substr(a.error_code,  position(',' in a.error_code)+1, Characters(a.error_code)-position(',' in a.error_code))))-1) in ('F010', 'FC542', 'FB012' 'FB943', 'NA') )

THEN 'No'

ELSE 'Yes'

end Error_Module,

...
FROM Error_code_table a

WHERE Error_Module = 'Yes'

作为一个方面,Characters() 函数与 Length() 相同。

谢谢, 迈克

【问题讨论】:

  • 正如 Bob Jarvis 所观察到的,单个字段中以逗号分隔的列表中的多个值使这变得更加困难。我会进一步说,如果可以避免的话,永远不应该这样做——这违反了第一范式,完全违背了所有关系设计原则。
  • 我同意,不幸的是,这就是数据库的设置方式,也是我必须使用的。

标签: sql mysql list filter teradata


【解决方案1】:

在包含在单个列中的逗号分隔列表中包含多个值会使这变得更加困难。如果可以对其进行重新设计,以使每行只有一个错误代码,则此任务会容易得多。

我对 Teradata 并不熟悉,但从 Google 看来,他们在分析和商业智能方面表现出色。因此,我希望他们有一些可用的正则表达式功能,我认为这将是您开始寻找的好地方。例如,在 Oracle 中,我会执行以下操作来从字符串中提取错误代码:

SELECT TRIM(REGEXP_REPLACE(ERROR_CODES, '(.*),.*,.*', '\1')),
       TRIM(REGEXP_REPLACE(ERROR_CODES, '.*,(.*),.*', '\1')),
       TRIM(REGEXP_REPLACE(ERROR_CODES, '.*,.*,(.*)', '\1'))
  INTO strErr1, strErr2, strErr3
  FROM DUAL;

祝你好运。

【讨论】:

  • 正则表达式支持在 Teradata 12 版之前不可用。它应该在 Teradata 13 或 13.10 中可用
【解决方案2】:

如果错误代码没有出现在列表的开头,它将始终以 ,<error code>, 的形式出现。

SELECT
    CASE
        WHEN substr(a.error_code, 1, position(',' in a.error_code) - 1) in ('F010', 'FC542', 'FB012', 'FB943', 'NA')
            OR a.error_code LIKE ANY ('%,F010,%', '%,FC542,%', '%,FB012,%', '%,FB943,%', '%,NA,%')
        THEN 'No'
        ELSE 'Yes'
    End Error_Module
FROM Error_code_table a
WHERE Error_Module = 'Yes';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 2011-05-13
    • 1970-01-01
    相关资源
    最近更新 更多