Postgres:选择具有大于1的字段数的所有行

时间:2016-04-01 14:24:44

标签: sql postgresql

我有存储产品价格信息的表,该表看起来类似于(不是主键)

no   name    price    date
1    paper   1.99     3-23
2    paper   2.99     5-25
3    paper   1.99     5-29
4    orange  4.56     4-23
5    apple   3.43     3-11

现在我想选择" name"的所有行。字段在表中不止一次出现。基本上,我希望我的查询返回前三行。

我试过了:

SELECT * FROM product_price_info GROUP BY name HAVING COUNT(*) > 1  

但我收到错误说:

  

专栏" product_price_info.no​​"必须出现在GROUP BY子句中或用于聚合函数

4 个答案:

答案 0 :(得分:24)

SELECT * 
FROM product_price_info 
WHERE name IN (SELECT name 
               FROM product_price_info 
               GROUP BY name HAVING COUNT(*) > 1)

答案 1 :(得分:7)

试试这个:

SELECT no, name, price, "date"
FROM (
  SELECT no, name, price, "date",
         COUNT(*) OVER (PARTITION BY name) AS cnt 
  FROM product_price_info ) AS t
WHERE t.cnt > 1

您可以使用COUNT的窗口版本来获取每个name分区的填充。然后,在外部查询中,筛选出具有小于2的填充的name分区。

答案 2 :(得分:4)

Window Functions非常好。

SELECT p.*, count(*) OVER (PARTITION BY name) FROM product p;

完整的例子:

CREATE TABLE product (no SERIAL, name text, price NUMERIC(8,2), date DATE);

INSERT INTO product(name, price, date) values
('paper', 1.99, '2017-03-23'),
('paper', 2.99, '2017-05-25'),
('paper', 1.99, '2017-05-29'),
('orange', 4.56, '2017-04-23'),
('apple', 3.43, '2017-03-11')
;

SELECT p.*, count(*) OVER (PARTITION BY name) FROM product p;

给出:

 no |  name  | price |    date    | count
----+--------+-------+------------+-------
  5 | apple  |  3.43 | 2017-03-11 |     1
  4 | orange |  4.56 | 2017-04-23 |     1
  1 | paper  |  1.99 | 2017-03-23 |     3
  2 | paper  |  2.99 | 2017-05-25 |     3
  3 | paper  |  1.99 | 2017-05-29 |     3
(5 rows)

答案 3 :(得分:2)

自我加入版本,使用返回多次出现的名称的子查询。

select t1.*
from tablename t1
join (select name from tablename group by name having count(*) > 1) t2
  on t1.name = t2.name

基本上与IN / EXISTS版本相同,但可能会更快一些。