Sql GROUP BY未按预期工作
这是我的样本表,只有一点信息Sql GROUP BY未按预期工作,sql,postgresql,aggregate,Sql,Postgresql,Aggregate,这是我的样本表,只有一点信息 select * from juniper_fpc'; id | router | part_name -----------+-----------+-------------------- 722830939 | BBBB-ZZZ1 | MPC-3D-16XGE-SFPP 722830940 | BBBB-ZZZ1 | MPC-3D-16XGE-SFPP 723103163 | AAAA-ZZZ1
select * from juniper_fpc';
id | router | part_name
-----------+-----------+--------------------
722830939 | BBBB-ZZZ1 | MPC-3D-16XGE-SFPP
722830940 | BBBB-ZZZ1 | MPC-3D-16XGE-SFPP
723103163 | AAAA-ZZZ1 | DPCE-R-40GE-SFP
723103164 | AAAA-ZZZ1 | MPC-3D-16XGE-SFPP
723103172 | AAAA-ZZZ1 | DPCE-R-40GE-SFP
722830941 | BBBB-ZZZ1 | MPC-3D-16XGE-SFPP
我要做的是从router列中识别只有part_名称条目以MPC开头的元素。我想到的是这个,但它是错误的,因为它列出了上述两个元素
SELECT router
FROM juniper_fpc
WHERE part_name LIKE 'MPC%'
GROUP BY router
ORDER BY router;
router
-----------
AAAA-ZZZ1
BBBB-ZZZ1
如果您的意思是只选择那些路由器,它们的所有部件名称都以MPC开头,那么您的查询应该是:
SELECT s.router
FROM juniper_fpc s
WHERE NOT EXISTS(select distinct id from juniper_fpc t
where t.id = s.id part_name NOT LIKE 'MPC%')
GROUP BY s.router
ORDER BY s.router;
如果您的意思是只选择那些路由器,它们的所有部件名称都以MPC开头,那么您的查询应该是:
SELECT s.router
FROM juniper_fpc s
WHERE NOT EXISTS(select distinct id from juniper_fpc t
where t.id = s.id part_name NOT LIKE 'MPC%')
GROUP BY s.router
ORDER BY s.router;
假设您想要的路由器只有部分名称,如“MPC%”,则可以使用条件计数:
select * from (
select router,
count(case when part_name like 'MPC%' then 1 else null end) as cnt_mpc,
count(*) as cnt_overall
from juniper_fpc
group by router) v_inner
where cnt_mpc = cnt_overall
这可以写得更紧凑,尽管可读性稍差
select router
from juniper_fpc
group by router
having count(case when part_name like 'MPC%' then 1 else null end) = count(*)
假设您想要的路由器只有部分名称,如“MPC%”,则可以使用条件计数:
select * from (
select router,
count(case when part_name like 'MPC%' then 1 else null end) as cnt_mpc,
count(*) as cnt_overall
from juniper_fpc
group by router) v_inner
where cnt_mpc = cnt_overall
这可以写得更紧凑,尽管可读性稍差
select router
from juniper_fpc
group by router
having count(case when part_name like 'MPC%' then 1 else null end) = count(*)
这应该表现良好:
SELECT j1.router
FROM (
SELECT router
FROM juniper_fpc
WHERE part_name LIKE 'MPC%'
GROUP BY router
) j1
LEFT JOIN juniper_fpc j2 ON j2.router = j1.router
AND j2.part_name NOT LIKE 'MPC%'
WHERE j2.router IS NULL
ORDER BY j1.router;
如果你做得对的话,也不存在可以工作的人:
SELECT router
FROM juniper_fpc j
WHERE NOT EXISTS (
SELECT 1
FROM juniper_fpc
WHERE router = j.router
AND part_name NOT LIKE 'MPC%'
)
GROUP BY router
ORDER BY router;
详情:
或者,使用Postgres 9.4或更高版本的语法:
SELECT router
FROM juniper_fpc
GROUP BY router
HAVING count(*) = count(*) FILTER (WHERE part_name LIKE 'MPC%')
ORDER BY router;
最好使用路由器上的索引,每个路由器的部件名。这应该可以很好地执行:
SELECT j1.router
FROM (
SELECT router
FROM juniper_fpc
WHERE part_name LIKE 'MPC%'
GROUP BY router
) j1
LEFT JOIN juniper_fpc j2 ON j2.router = j1.router
AND j2.part_name NOT LIKE 'MPC%'
WHERE j2.router IS NULL
ORDER BY j1.router;
如果你做得对的话,也不存在可以工作的人:
SELECT router
FROM juniper_fpc j
WHERE NOT EXISTS (
SELECT 1
FROM juniper_fpc
WHERE router = j.router
AND part_name NOT LIKE 'MPC%'
)
GROUP BY router
ORDER BY router;
详情:
或者,使用Postgres 9.4或更高版本的语法:
SELECT router
FROM juniper_fpc
GROUP BY router
HAVING count(*) = count(*) FILTER (WHERE part_name LIKE 'MPC%')
ORDER BY router;
最好使用路由器上的索引,每个路由器的部件名。您也可以在此处打开函数:
SELECT
*
FROM
(
SELECT
router,
part_name,
COUNT(distinct part_name) OVER (PARTITION BY router) as count_of_distinct_parts
FROM juniper_fpc
)subqry
WHERE part_name like 'MPC%' AND count_of_distinct_parts = 1
如果此查询范围扩大,这将为更复杂的情况打开大门。您也可以在此处选择窗口功能:
SELECT
*
FROM
(
SELECT
router,
part_name,
COUNT(distinct part_name) OVER (PARTITION BY router) as count_of_distinct_parts
FROM juniper_fpc
)subqry
WHERE part_name like 'MPC%' AND count_of_distinct_parts = 1
如果此查询范围扩大,这将为更复杂的情况打开大门。我看不出您的代码或输出有任何错误,根据u,这两个都应该返回!您的输入数据包含| AAAA-ZZZ1 | MPC-3D-16XGE-SFPP |和| BBBB-ZZZ1 | MPC-3D-16XGE-SFPP |,因此PostgreSQL返回正确的结果。您是否需要只包含部分名称(如“MPC”)而不包含其他名称的记录?也许您希望看到MPC-3D-16XGE-SFPP没有路由器名称“bbbbb-ZZZ1”?在这种情况下,您应该分组并按部件名称排序。我看不出您的代码或输出有任何错误,根据u,这两个都应该返回!您的输入数据包含| AAAA-ZZZ1 | MPC-3D-16XGE-SFPP |和| BBBB-ZZZ1 | MPC-3D-16XGE-SFPP |,因此PostgreSQL返回正确的结果。您是否需要只包含部分名称(如“MPC”)而不包含其他名称的记录?也许您希望看到MPC-3D-16XGE-SFPP没有路由器名称“bbbbb-ZZZ1”?在这种情况下,您应该按部件名称分组和排序。问题:您不能在子查询中引用未聚合的s.id;区别是没有用的;缺少和.问题:无法在子查询中引用未聚合的s.id;区别是没有用的;失踪和失踪。