0

我今天有一个白痴日。我敢肯定这相对简单,但我的大脑并没有给我答案。

我有一个表,其行是对象类型。看起来像这样:

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 有狗时,会输入一个狗的记录。

我现在需要更新此表,以便每种类型的对象(猫、狗、鸟)都有给定 house_id 的记录。我想通过插入一个选择查询的结果来做到这一点,该查询为每种类型返回一条记录,当且仅当不存在记录时,该类型的行中“foo”和“bar”的最早值对于具有给定 house_id 的类型。

因此,对于上面的示例数据,给定的 house_id = 3,选择查询将返回以下内容:

name    foo    bar    house_id
Cat     12     4      3
Dog     8      23     3

然后我可以将其直接插入表中。

基本上,如果没有具有给定 house_id 的名称的行,则返回每个不同名称的第一行。

欢迎提出建议。如果有帮助,数据库引擎是 postgres。

4

2 回答 2

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)
于 2012-05-28T16:51:22.543 回答
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
 );
于 2012-05-28T15:46:04.517 回答