SQL - GROUP BY & HAVING COUNT 问题

SQL - GROUP BY & HAVING COUNT issue

我已经研究并发现 questions/answers 和我这里的问题一样,但我找不到完全合适的东西。

SELECTING with multiple WHERE conditions on same column --- 这个 link 非常接近,但仍然不能解决我的问题。

问题: 我有一个 table 包含付款方式和付款状态(空白状态可以)

SEL_PRO_PMTMETHOD_PK    SEL_PROFILE_DETAIL_FK   PMT_TYPE    PMT_STATUS
43827                   342997                  EFT         G
43828                   342997                  EFT         P
43829                   342997                  RCC  
43826                   342997                  EFT  

43776                   342922                  EFT  
43777                   342922                  EFT         G
43778                   342922                  EFT         P

我需要通过 SEL_PROFILE_DETAIL_FK 开发独特的输出,这取决于它是否只有 EFTs 条目,只有 RCC 条目,或者同时有 EFT 和 RCC 条目。

我找到了仅适用于 EFT 和仅适用于 RCC 的简单方法

但我需要能够判断 FK 分组中是否同时存在 EFT 和 RCC 条目。

到目前为止我的代码:

SELECT pmt_type
FROM   sel_pro_pmtmethod
WHERE  sel_profile_detail_fk = '342997'    
  AND  pmt_type IN ('EFT', 'RCC')
GROUP  BY pmt_type
HAVING COUNT(distinct pmt_type) >= 1

此代码返回 pmt_type 以上两组数据。它是否同时具有 EFT 和 RCC,或者只有 EFT 并不重要。

我已将 HAVING COUNT 子句更改为“= 2”,但 returns 什么都没有,因为 RCC 的计数 = 1 且 EFT = 3。

但是我需要的是这个 WHERE / GROUP BY / HAVING 场景是真实的是分组中是否有 EFT AND RCC 条目。如果缺少一个则失败。

试试这个:

SELECT SEL_PROFILE_DETAIL_FK
FROM   sel_pro_pmtmethod
WHERE  pmt_type IN ('EFT', 'RCC')
GROUP  BY SEL_PROFILE_DETAIL_FK
HAVING MIN(pmt_type) <> MAX(pmt_type)
SELECT SEL_PROFILE_DETAIL_FK
FROM   sel_pro_pmtmethod
WHERE  pmt_type IN ('EFT', 'RCC')
GROUP  BY SEL_PROFILE_DETAIL_FK
HAVING COUNT(distinct pmt_type) = 2

你的分组依据是错误的。按 pmt_type 分组意味着每行仅显示一种类型。因为你想要它的外键,你需要按那个分组。

DISTINCT 意味着它只会计算每个值出现 1 次。

如果你真的想要所有相关的记录,你可以使用window函数条件聚合:

SELECT *
FROM
    (
       SELECT
          *
          ,COUNT(CASE WHEN PMT_TYPE = 'EFT' THEN PMT_TYPE END) OVER (PARTITION BY SEL_PROFILE_DETAIL_FK) EftCount
          ,COUNT(CASE WHEN PMT_TYPE = 'RCC' THEN PMT_TYPE END) OVER (PARTITION BY SEL_PROFILE_DETAIL_FK) RCCCount
       FROM
          sel_pro_pmtmethod
       WHERE
          PMT_TYPE IN ('EFT','RCC')
    ) t
WHERE
    t.EftCount > 0
    AND t.RCCCount > 0

或者另一种获取所有原始记录的方法是采用第一种方法并在相关子查询中使用 EXISTS,如下所示:

SELECT *
FROM
    sel_pro_pmtmethod m1
WHERE
    EXISTS (SELECT 1
          FROM   sel_pro_pmtmethod m2
          WHERE
             m1.SEL_PROFILE_DETAIL_FK = m2.SEL_PROFILE_DETAIL_FK
             m2.pmt_type IN ('EFT', 'RCC')
          GROUP  BY m2.SEL_PROFILE_DETAIL_FK
          HAVING COUNT(distinct m2.pmt_type) = 2

并解决你的这一部分 post "I need to develop unique output by SEL_PROFILE_DETAIL_FK depending on whether it has ONLY EFTs entries, ONLY RCC entries, or BOTH EFT and RCC entries." 这听起来好像你实际上不想限制在它们都存在但知道是一个还是另一个或两者都存在的情况下存在,您可以像这样使用 conditional aggregation 来做到这一点:

SELECT
    SEL_PROFILE_DETAIL_FK
    ,CASE
       WHEN EFTCount > 0 AND RCCCount > 0 THEN 'Both'
       WHEN RCCCount > 0 THEN 'RCC'
       ELSE 'EFT'
    END as PmtTypesPresent

FROM
    (
    SELECT
       SEL_PROFILE_DETAIL_FK
       ,COUNT(CASE WHEN PMT_TYPE = 'EFT' THEN PMT_TYPE END) as EFTCount
       ,COUNT(CASE WHEN PMT_TYPE = 'RCC' THEN PMT_TYPE END) as RCCCount
    FROM   sel_pro_pmtmethod
    WHERE  pmt_type IN ('EFT', 'RCC')
    GROUP  BY SEL_PROFILE_DETAIL_FK
) t