【问题标题】:Returning a row if and only if a sibling row doesn't exist当且仅当兄弟行不存在时才返回一行
【发布时间】:2012-06-02 23:05:27
【问题描述】:

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

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

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。

【问题讨论】:

  • 你对 'foo' 和 'bar' 的“最早” vañues 的定义是什么?
  • 具有最低 id 的该类型的行中的值。
  • 那种房子还是那种动物?
  • 那种动物。不过,我很确定我现在有一个解决方案。
  • 我也是。你展示你的,我展示我的。你先!

标签: sql


【解决方案1】:

通常情况下,我整个上午都在纠结一个问题,将其发布到 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
 );

【讨论】:

  • 满足我的需要。我也不确定它还能从哪里获得价值。
  • 嗯:当然是两个领域的cathesian产品!
【解决方案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)

【讨论】:

  • 我已经用我的解决方案完成了这项工作,但我正在记下这个。谢谢。
猜你喜欢
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多