我有一个表,其行是对象的类型。看起来像这样:
id name foo bar house_id
1 Cat 12 4 1
2 Cat 9 4 2
3 Dog 8 23 1
4 Bird 9 54 1
5 Bird 78 2 2
6 Bird 29 32 3
这不是我选择实施它的方式,但这正是我正在使用的方式。物品(猫,狗和鸟,在现实生活中它们是真正的商业用品)已被临时添加到表中。当house_id 1中需要猫时,猫的记录会被放入。当house_id 3获取狗时,会记录下狗的记录。
我现在需要更新此表,以便每个类型的对象(Cat,Dog,Bird)都有给定house_id的记录。我想通过插入select查询的结果来执行此操作,该查询返回每种类型的单个记录,当前和仅当没有现有记录时,来自该类型行的'foo'和'bar'的最早值对于具有给定house_id的那种类型。
因此对于上面的示例数据,给定的house_id = 3,select查询将返回以下内容:
name foo bar house_id
Cat 12 4 3
Dog 8 23 3
然后我可以直接插入表格。
基本上,如果给定的house_id没有该名称的行,则返回每个不同名称的第一行。
欢迎提出建议。如果有帮助,数据库引擎就是postgres。
答案 0 :(得分:2)
SET search_path= 'tmp';
DROP TABLE dogcat CASCADE;
CREATE TABLE dogcat
( id serial NOT NULL
, zname varchar
, foo INTEGER
, bar INTEGER
, house_id INTEGER NOT NULL
, PRIMARY KEY (zname,house_id)
);
INSERT INTO dogcat(zname,foo,bar,house_id) VALUES
('Cat',12,4,1)
,('Cat',9,4,2)
,('Dog',8,23,1)
,('Bird',9,54,1)
,('Bird',78,2,2)
,('Bird',29,32,3)
;
-- Carthesian product of the {name,house_id} domains
WITH cart AS (
WITH beast AS (
SELECT distinct zname AS zname
FROM dogcat
)
, house AS (
SELECT distinct house_id AS house_id
FROM dogcat
)
SELECT beast.zname AS zname
,house.house_id AS house_id
FROM beast , house
)
INSERT INTO dogcat(zname,house_id, foo,bar)
SELECT ca.zname, ca.house_id
,fb.foo, fb.bar
FROM cart ca
-- find the animal with the lowes id
JOIN dogcat fb ON fb.zname = ca.zname AND NOT EXISTS
( SELECT * FROM dogcat nx
WHERE nx.zname = fb.zname
AND nx.id < fb.id
)
WHERE NOT EXISTS (
SELECT * FROM dogcat dc
WHERE dc.zname = ca.zname
AND dc.house_id = ca.house_id
)
;
SELECT * FROM dogcat;
结果:
SET
DROP TABLE
NOTICE: CREATE TABLE will create implicit sequence "dogcat_id_seq" for serial column "dogcat.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "dogcat_pkey" for table "dogcat"
CREATE TABLE
INSERT 0 6
INSERT 0 3
id | zname | foo | bar | house_id
----+-------+-----+-----+----------
1 | Cat | 12 | 4 | 1
2 | Cat | 9 | 4 | 2
3 | Dog | 8 | 23 | 1
4 | Bird | 9 | 54 | 1
5 | Bird | 78 | 2 | 2
6 | Bird | 29 | 32 | 3
7 | Cat | 12 | 4 | 3
8 | Dog | 8 | 23 | 2
9 | Dog | 8 | 23 | 3
(9 rows)
答案 1 :(得分:0)
通常情况下,我整个上午都在努力解决问题,将其发布到Stack Overflow并在接下来的半小时内自行解决
select name, foo, bar, 3
from table
where id in
(
select min(id) from table where name not in
(
select name from table where house_id = 3
)
group by name
);