2016-04-01 42 views
3

我有表,用於存儲產品的價格信息,該表類似於計數,(沒有是主鍵)Postgres的:選擇所有的行與現場大於1

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 

現在我想選擇表中「姓名」字段不止一次出現的所有行。基本上,我想我的查詢返回前三行。

我想:

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

,但我得到一個錯誤說:

列 「product_price_info.no​​」 必須出現在GROUP BY子句或聚合函數中使用

回答

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

試試這個:

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分區的填充。然後,在外部查詢中,篩選出name羣體小於2的分區。

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版本,但可能有點快。

0

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)