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
我已经研究并发现 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