2012-05-28 4 views
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 получает собак, запись вводится собакам.

Теперь мне нужно обновить эту таблицу, так что каждый Тип объекта (Cat, Dog, Bird) имеет запись для данного house_id. Я хочу сделать это, вставив результат из запроса select, который возвращает одну запись для каждого типа, с самыми ранними значениями для «foo» и «bar» из строки этого типа, если и только если нет существующей записи для этого типа с данным house_id.

Таким образом, для приведенного выше примера данных, где данная house_id = 3, то запрос на выборку будет возвращать следующее:

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

, который можно затем вставить прямо в таблице.

В принципе, верните первую строку каждого отдельного имени, если нет строк этого имени с заданным house_id.

Предложения приветствуются. Двигатель БД - postgres, если это помогает.

+0

Каково ваше определение «самых ранних» vañues для «foo» и «bar»? – Sebas

+0

Значения из строки этого типа с наименьшим идентификатором. –

+0

Этот тип дома или этого вида животных? – wildplasser

ответ

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) 
+0

Я проделал работу с моим решением, но я запомнил это. Спасибо. –

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 
); 
+0

У вас есть house_id = 3 hardcoded. – wildplasser

+0

Этого достаточно для моих нужд. Я также не знаю, где еще он может получить значение. –

+0

Ну, из соевого продукта двух доменов, конечно! – wildplasser

Смежные вопросы