我有存储产品价格信息的表,该表看起来类似于(不是主键)
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子句中或用于聚合函数
答案 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
版本相同,但可能会更快一些。