改进 Netezza SQL 在 WHERE 子句中包含数百个字符串的查询

Improve Netezza SQL Query That Contains Hundreds of Strings in WHERE Clause

我有一个 Netezza 查询,其中包含数百个潜在字符串的 WHERE 子句。我很惊讶它能运行,但它需要时间才能完成并且偶尔会出错 ('transaction rolled back by client')。这是我查询的伪代码版本。

SELECT
    TO_CHAR(X.I_TS, 'YYYY-MM-DD') AS DATE,
    X.I_SRC_NM AS CHANNEL,
    X.I_CD AS CODE,
    COUNT(DISTINCT CASE WHEN X.I_FLG = 1 THEN X.UID ELSE NULL) AS WIDGETS

FROM
    (SELECT
        A.I_TS,
        A.I_SRC_NM,
        A.I_CD,
        B.UID,
        B.I_FLG

    FROM
        SCHEMA.DATABASE.TABLE_A A
        LEFT JOIN SCHEMA.DATABASE.TABLE_B B ON A.UID = B.UID

    WHERE
        A.I_TS BETWEEN '2017-01-01' AND '2017-01-15'
        AND B.TAB_CODE IN ('00AV', '00BX', '00C2', '00DJ'...
                           ...
                           ...
                           ...
                           ...
                           ...
                           ...
                           ...)
    ) X

GROUP BY
    X.I_TS,
    X.I_SRC_NM,
    X.I_CD
;

在我的查询中,我将 B.TAB_CODE 的结果限制为大约 1,200 个值(超过 10k)。老实说,我很惊讶它能正常工作,但大部分时间都是这样。

有没有更有效的方法来处理这个问题?

如果IN 子句太麻烦,您可以分多个部分进行查询。创建一个包含 TAB_CODE 集的临时 table,然后在 JOIN.

中使用它
WITH tab_codes(tab_code) AS (
 SELECT '00AV' 
 UNION ALL
 SELECT '00BX' 
 --- etc ---
)
SELECT
  TO_CHAR(X.I_TS, 'YYYY-MM-DD') AS DATE,
  X.I_SRC_NM AS CHANNEL,
  --- etc ---
  INNER JOIN tab_codes Q ON B.TAB_CODES = Q.tab_code

如果您想进一步提高性能,请考虑使用真正的临时 table (CTAS)

  1. 如果我猜对了,X.I_TS 实际上是一个“时间戳”,因此我希望它每天包含许多不同的值。你能证实吗? 如果我是对的,查询可能会受益于将“group by X.I._TS,...”更改为“group by 1,...”

  2. 此外,'Count(Distinct Case...' 永远不会 return 除了 1 或 NULL 之外的任何其他值。你能确认吗? 如果我是对的,您可以通过将其更改为“MAX(Case...”

  3. 来摆脱昂贵的“DISTINCT”

可以关注我吗:)

我们已经看到 "cheaper" 将原始 table CTAS 到另一个,根据您的主要条件分发,然后查询 table 的情况。