Oracle SQL - 将行保留在特定列类别中列值较多的组中
Oracle SQL - Keep rows within group where there are larger number of values for column, in a specific column category
我需要弄清楚如何从下面的 table 中获取结果,并且只显示图像中绿色突出显示的行。在每个 account_id/site_id 组合中(示例中显示了两个 - 123/usa 和 456/can),我只需要保留 group_ids,其中 Y(标志)的数量更多品牌(如 side_id“罐头”所示 - group_id 1 中该品牌的 Y 多于 group_id 2 中的 Y。在 account_id/site 组合中,如果有两个 group_ids 具有超过两个 Y 的品牌,则将它们都保留(如 site_id “美国”中所示)。
group_id
account_id
site_id
brand
flag
1
123
usa
toyota
N
1
123
usa
toyota
N
1
123
usa
tesla
Y
1
123
usa
tesla
Y
2
123
usa
toyota
Y
2
123
usa
toyota
N
2
123
usa
tesla
Y
2
123
usa
tesla
N
3
123
usa
toyota
Y
3
123
usa
toyota
N
3
123
usa
tesla
Y
3
123
usa
tesla
N
4
123
usa
toyota
Y
4
123
usa
toyota
Y
4
123
usa
tesla
N
4
123
usa
tesla
N
1
456
can
honda
Y
1
456
can
honda
Y
1
456
can
honda
Y
2
456
can
honda
Y
2
456
can
honda
N
2
456
can
honda
Y
通过组合使用window个函数,可以统计每个group/account/site/brand的Y flags个数,然后求出用另一个解析函数划分的最大Y flags个数,然后只有 return 这两个值匹配的行。
查询
WITH
grps (GROUP_ID,
account_id,
site_id,
brand,
flag)
AS
(SELECT 1, 123, 'usa', 'toyota', 'N' FROM DUAL
UNION ALL
SELECT 1, 123, 'usa', 'toyota', 'N' FROM DUAL
UNION ALL
SELECT 1, 123, 'usa', 'tesla', 'Y' FROM DUAL
UNION ALL
SELECT 1, 123, 'usa', 'tesla', 'Y' FROM DUAL
UNION ALL
SELECT 2, 123, 'usa', 'toyota', 'Y' FROM DUAL
UNION ALL
SELECT 2, 123, 'usa', 'toyota', 'N' FROM DUAL
UNION ALL
SELECT 2, 123, 'usa', 'tesla', 'Y' FROM DUAL
UNION ALL
SELECT 2, 123, 'usa', 'tesla', 'N' FROM DUAL
UNION ALL
SELECT 3, 123, 'usa', 'toyota', 'Y' FROM DUAL
UNION ALL
SELECT 3, 123, 'usa', 'toyota', 'N' FROM DUAL
UNION ALL
SELECT 3, 123, 'usa', 'tesla', 'Y' FROM DUAL
UNION ALL
SELECT 3, 123, 'usa', 'tesla', 'N' FROM DUAL
UNION ALL
SELECT 4, 123, 'usa', 'toyota', 'Y' FROM DUAL
UNION ALL
SELECT 4, 123, 'usa', 'toyota', 'Y' FROM DUAL
UNION ALL
SELECT 4, 123, 'usa', 'tesla', 'N' FROM DUAL
UNION ALL
SELECT 4, 123, 'usa', 'tesla', 'N' FROM DUAL
UNION ALL
SELECT 1, 456, 'can', 'honda', 'Y' FROM DUAL
UNION ALL
SELECT 1, 456, 'can', 'honda', 'Y' FROM DUAL
UNION ALL
SELECT 1, 456, 'can', 'honda', 'Y' FROM DUAL
UNION ALL
SELECT 2, 456, 'can', 'honda', 'Y' FROM DUAL
UNION ALL
SELECT 2, 456, 'can', 'honda', 'N' FROM DUAL
UNION ALL
SELECT 2, 456, 'can', 'honda', 'Y' FROM DUAL)
SELECT g3.GROUP_ID,
g3.account_id,
g3.site_id,
g3.brand,
g3.flag
FROM (SELECT g2.*, MAX (g2.y_flag_cnt) OVER (PARTITION BY account_id) AS max_y_flag_cnt
FROM (SELECT g.*,
SUM (CASE WHEN flag = 'Y' THEN 1 ELSE 0 END)
OVER (PARTITION BY GROUP_ID,
account_id,
site_id,
brand) AS y_flag_cnt
FROM grps g) g2) g3
WHERE flag = 'Y' AND y_flag_cnt = max_y_flag_cnt
ORDER BY account_id, GROUP_ID;
输出
GROUP_ID ACCOUNT_ID SITE_ID BRAND FLAG
___________ _____________ __________ _________ _______
1 123 usa tesla Y
1 123 usa tesla Y
4 123 usa toyota Y
4 123 usa toyota Y
1 456 can honda Y
1 456 can honda Y
1 456 can honda Y
我需要弄清楚如何从下面的 table 中获取结果,并且只显示图像中绿色突出显示的行。在每个 account_id/site_id 组合中(示例中显示了两个 - 123/usa 和 456/can),我只需要保留 group_ids,其中 Y(标志)的数量更多品牌(如 side_id“罐头”所示 - group_id 1 中该品牌的 Y 多于 group_id 2 中的 Y。在 account_id/site 组合中,如果有两个 group_ids 具有超过两个 Y 的品牌,则将它们都保留(如 site_id “美国”中所示)。
group_id | account_id | site_id | brand | flag |
---|---|---|---|---|
1 | 123 | usa | toyota | N |
1 | 123 | usa | toyota | N |
1 | 123 | usa | tesla | Y |
1 | 123 | usa | tesla | Y |
2 | 123 | usa | toyota | Y |
2 | 123 | usa | toyota | N |
2 | 123 | usa | tesla | Y |
2 | 123 | usa | tesla | N |
3 | 123 | usa | toyota | Y |
3 | 123 | usa | toyota | N |
3 | 123 | usa | tesla | Y |
3 | 123 | usa | tesla | N |
4 | 123 | usa | toyota | Y |
4 | 123 | usa | toyota | Y |
4 | 123 | usa | tesla | N |
4 | 123 | usa | tesla | N |
1 | 456 | can | honda | Y |
1 | 456 | can | honda | Y |
1 | 456 | can | honda | Y |
2 | 456 | can | honda | Y |
2 | 456 | can | honda | N |
2 | 456 | can | honda | Y |
通过组合使用window个函数,可以统计每个group/account/site/brand的Y flags个数,然后求出用另一个解析函数划分的最大Y flags个数,然后只有 return 这两个值匹配的行。
查询
WITH
grps (GROUP_ID,
account_id,
site_id,
brand,
flag)
AS
(SELECT 1, 123, 'usa', 'toyota', 'N' FROM DUAL
UNION ALL
SELECT 1, 123, 'usa', 'toyota', 'N' FROM DUAL
UNION ALL
SELECT 1, 123, 'usa', 'tesla', 'Y' FROM DUAL
UNION ALL
SELECT 1, 123, 'usa', 'tesla', 'Y' FROM DUAL
UNION ALL
SELECT 2, 123, 'usa', 'toyota', 'Y' FROM DUAL
UNION ALL
SELECT 2, 123, 'usa', 'toyota', 'N' FROM DUAL
UNION ALL
SELECT 2, 123, 'usa', 'tesla', 'Y' FROM DUAL
UNION ALL
SELECT 2, 123, 'usa', 'tesla', 'N' FROM DUAL
UNION ALL
SELECT 3, 123, 'usa', 'toyota', 'Y' FROM DUAL
UNION ALL
SELECT 3, 123, 'usa', 'toyota', 'N' FROM DUAL
UNION ALL
SELECT 3, 123, 'usa', 'tesla', 'Y' FROM DUAL
UNION ALL
SELECT 3, 123, 'usa', 'tesla', 'N' FROM DUAL
UNION ALL
SELECT 4, 123, 'usa', 'toyota', 'Y' FROM DUAL
UNION ALL
SELECT 4, 123, 'usa', 'toyota', 'Y' FROM DUAL
UNION ALL
SELECT 4, 123, 'usa', 'tesla', 'N' FROM DUAL
UNION ALL
SELECT 4, 123, 'usa', 'tesla', 'N' FROM DUAL
UNION ALL
SELECT 1, 456, 'can', 'honda', 'Y' FROM DUAL
UNION ALL
SELECT 1, 456, 'can', 'honda', 'Y' FROM DUAL
UNION ALL
SELECT 1, 456, 'can', 'honda', 'Y' FROM DUAL
UNION ALL
SELECT 2, 456, 'can', 'honda', 'Y' FROM DUAL
UNION ALL
SELECT 2, 456, 'can', 'honda', 'N' FROM DUAL
UNION ALL
SELECT 2, 456, 'can', 'honda', 'Y' FROM DUAL)
SELECT g3.GROUP_ID,
g3.account_id,
g3.site_id,
g3.brand,
g3.flag
FROM (SELECT g2.*, MAX (g2.y_flag_cnt) OVER (PARTITION BY account_id) AS max_y_flag_cnt
FROM (SELECT g.*,
SUM (CASE WHEN flag = 'Y' THEN 1 ELSE 0 END)
OVER (PARTITION BY GROUP_ID,
account_id,
site_id,
brand) AS y_flag_cnt
FROM grps g) g2) g3
WHERE flag = 'Y' AND y_flag_cnt = max_y_flag_cnt
ORDER BY account_id, GROUP_ID;
输出
GROUP_ID ACCOUNT_ID SITE_ID BRAND FLAG
___________ _____________ __________ _________ _______
1 123 usa tesla Y
1 123 usa tesla Y
4 123 usa toyota Y
4 123 usa toyota Y
1 456 can honda Y
1 456 can honda Y
1 456 can honda Y