PostgreSql在group by和需要再添加两列之间存在冲突

PostgreSql在group by和需要再添加两列之间存在冲突,postgresql,Postgresql,问题: 找出恰好被一个国家包围的内陆国家。报告身份证 以及内陆国的名称,然后是其周围国家的id和名称 输出表:Query3 属性: c1id (landlocked country id) [INTEGER] c1name (landlocked country name) [VARCHAR(20)] c2id (surrounding country id) [INTEGER] c2name (surrounding country name) [VARCHAR(20)] O

问题:

找出恰好被一个国家包围的内陆国家。报告身份证 以及内陆国的名称,然后是其周围国家的id和名称

输出表:Query3

属性:

  c1id (landlocked country id) [INTEGER]
  c1name (landlocked country name) [VARCHAR(20)]
  c2id (surrounding country id) [INTEGER]
  c2name (surrounding country name) [VARCHAR(20)]

Order by: c1name ASC
模式:

  • 国家表包含世界上所有国家及其事实
  • “cid”是国家的id
  • “name”是国家的名称
  • “高度”是国家的最高海拔点
  • “人口”是指国家的人口

    CREATE TABLE country (
        cid         INTEGER     PRIMARY KEY,
        cname       VARCHAR(20) NOT NULL,
        height      INTEGER     NOT NULL,
        population  INTEGER     NOT NULL);
    
  • 邻居表提供了有关这些国家及其邻国的信息

  • “国家”指第一个国家的cid

  • “邻居”指与第一个国家相邻的国家的cid
  • “长度”是指两个邻国之间的边界长度
注意,如果A和B是邻居,那么表中存储了两个元组来表示该信息(A,B)和(B,A)

我的尝试:

这是我最初的查询,它获取只有一个邻国的所有国家的名称和cid

SELECT c.cid   AS c1id,
       c.cname AS c1name
FROM   country c
       JOIN neighbour n
         ON n.country = c.cid
GROUP  BY c.cid,
          c.cname
HAVING Count(n.neighbor) = 1; 
问题是我还需要邻国的名称和国家id,因此我尝试这样做:

SELECT c.cid   AS c1id,
       c.cname AS c1name,
       n.neighbor,
       c2.cname
FROM   country c
       JOIN neighbour n
         ON n.country = c.cid
       JOIN country c2
         ON n.neighbor = c2.cid
GROUP  BY c.cid,
          c.cname
HAVING Count(n.neighbor) = 1; 
问题显然是因为n.Nexture和c2.cname不在group by子句中。如果我将它们添加到GROUPBY子句中,那么即使一个国家是多个邻国,计数(n.邻居)也会分别计算每个国家的邻国

例如,如果希腊(cid=1)与土耳其(cid=2)和德国(cid=3)相邻。加拿大(cid=4)与美国(cid=5)相邻,则第二个查询的输出将为

1 Greece 2 Turkey 1 Greece 3 Germany 4 Canada 5 USA 1希腊2土耳其 1希腊3德国 4加拿大5美国 而不是

4 Canada 5 USA 4加拿大5美国
我该如何着手解决这个问题呢?

我认为最简单的方法是

  • 解决“邻居”所需的连接,然后
  • 将第一个查询加入结果
样本数据

感谢您在问题中包含CREATETABLE语句

insert into country values
(1, 'Greece', 1, 1), (2, 'Turkey', 1, 1), (3, 'Germany', 1, 1), 
(4, 'Canada', 1, 1), (5, 'USA', 1, 1);

insert into neighbour values
(1, 2, 1), (2, 1, 1), (1, 3, 1), (3, 1, 1), 
(4, 5, 1), (5, 4, 1);
解析连接

select c1.cid , c1.cname as cname, c2.cid as nid, c2.cname as nname 
from neighbour n
inner join country c1 on c1.cid = n.country
inner join country c2 on c2.cid = n.neighbor;
加入您的第一个查询

前四行与上面的查询相同

select c1.cid , c1.cname as cname, c2.cid as nid, c2.cname as nname 
from neighbour n
inner join country c1 on c1.cid = n.country
inner join country c2 on c2.cid = n.neighbor
inner join (SELECT c.cid   AS c1id,
                   c.cname AS c1name
            FROM   country c
            JOIN neighbour n
              ON n.country = c.cid
            GROUP  BY c.cid, c.cname
            HAVING Count(n.neighbor) = 1) n2
on c1.cid = n2.c1id;
上面查询中的最后一个连接保证第一对列中的国家有一个邻居

cid cname nid nname -- 2 Turkey 1 Greece 3 Germany 1 Greece 4 Canada 5 USA 5 USA 4 Canada cid cname nid nname -- 2土耳其1希腊 3德国1希腊 4加拿大5美国 5美国4加拿大
哇,太谢谢你了!你解释得很清楚! cid cname nid nname -- 2 Turkey 1 Greece 3 Germany 1 Greece 4 Canada 5 USA 5 USA 4 Canada