SQL - GROUP BY&有COUNT个问题

时间:2016-12-09 16:58:35

标签: sql oracle having

我已经研究过并在这里找到了像我这样的问题/答案,但我找不到任何合适的答案。

SELECTING with multiple WHERE conditions on same column ---此链接非常接近,但仍无法解决我的问题。

问题: 我有一个表格,其中包含付款方式和付款状态(空白状态正常)

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开发唯一的输出,具体取决于它是仅有EFT条目,只有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”,但由于RCC的计数= 1且EFT = 3,因此不返回任何内容。

但我需要的是,如果在分组中存在EFT和RCC条目,则此WHERE / GROUP BY / HAVING场景为真。如果缺少一个则失败。

2 个答案:

答案 0 :(得分:2)

试试这个:

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)

答案 1 :(得分:2)

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次出现。

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

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

要解决帖子的这一部分&#34;我需要通过SEL_PROFILE_DETAIL_FK开发独特的输出,具体取决于它是仅有EFT条目,只有RCC条目,还是两个EFT和RCC条目。&#34;这听起来好像你实际上并不想限制它们只是当它们都是,但知道是否存在一个或另一个或两个,你可以用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