将PostgreSQL与pgadmin4一起使用,我有一个像这样的示例表:
dogs
+---+-------------------+------------+
|id |breed | birthPlace |
+---+-------------------+------------+
| 1 | Yorkshire Terrier | Berlin |
| 2 | Yorkshire Terrier | Berlin |
| 3 | Husky | New York |
| 4 | Yorkshire Terrier | Berlin |
| 5 | Husky | Amsterdam |
+---+-------------------+------------+
对于练习,我想通过breed
对我的桌子进行分组,确保至少有两只狗的一个品种,然后扔出所有组,其狗不是都有相同的{{1} 1}}。
我想我必须在下面的查询中设置birthPlace
所在的最后一个语句,但我对如何执行此操作一无所知:
?
答案 0 :(得分:4)
我想说的如下:
SELECT breed
FROM dogs
GROUP BY breed
HAVING COUNT(*) > 1 AND COUNT(DISTINCT birthPlace) = 1;
^^^ at least two dogs ^^^ same birthplace
HAVING
条款声称每个品种至少有两只狗,并且该品种只有一个不同的出生地。
答案 1 :(得分:2)
没有相同的出生地意味着最小值和最大值不同。这应该是如何解决问题的一个很大的暗示。
这很容易翻译成SQL:
Having Count(*) > 1 And min(birthPlace) <> max(birthPlace)
注意我已将COUNT(dogs.id)
更改为COUNT(*)
。那些应该做同样的事情,COUNT(*)
更容易打字和阅读。
您可能想要使用count(distinct birthplace)
。我不鼓励这样做。当您不需要时,请避免使用distinct
,因为它通常会产生比“更简单”更多的开销。聚合函数。
最后,这两种方法都忽略NULL
个值。可以通过包括and count(birthplace) = count(*)
来包含所有值都为非NULL的要求。
答案 2 :(得分:2)
带子查询的变体:
SELECT breed
FROM (
SELECT breed, birthPlace, count(*)::int AS ct
FROM dogs
GROUP BY 1, 2
) sub
GROUP BY 1
HAVING count(*) = 1 -- one birth place
AND sum(ct) > 1; -- more than one row
应该是最快的技术之一。
强制转换为整数(::int
)是可选的。避免升级到外部numeric
中的数据类型SELECT
。没关系。
答案 3 :(得分:0)
在plsql
中你必须做这样的事情(假设id不是真正的列):
With que as
(
SELECT breed, birthplace, count(distinct birthplace) over (partition by breed) counter
FROM dog
)
SELECT breed, birthplace
FROM que
WHERE counter = 1
GROUP BY breed, birthplace, counter
HAVING count(breed) > 1