Postgresql

從 SELECT 中插入並結合單個值

  • May 26, 2014

我有這個查詢返回幾行item_id

select item_id from properties where name like 'body';   

我有第二個返回 1 行tag_id

select id from tags where name ilike '%hoax%';   

我想使用這兩個結果在第三個表中創建新行,item_tags以便我可以將item_id第一個查詢中的每一個插入tag_id第二個查詢中。

我會有類似的東西:

INSERT INTO item_tags (item_id, tag_id) VALUES (item_id1, tag_id);  
INSERT INTO item_tags (item_id, tag_id) VALUES (item_id2, tag_id);
INSERT INTO item_tags (item_id, tag_id) VALUES (item_id3, tag_id);   
...     

第一個查詢返回 800 多行。如何自動化插入?

psql 9.1.11,Postgres 9.1.4。

基本的INSERT

INSERT INTO item_tags (item_id, tag_id)
SELECT p.item_id, t.id
FROM  (SELECT item_id FROM properties WHERE name LIKE 'body') p
   , (SELECT id FROM tags WHERE name ILIKE '%hoax%') t

FROM 子句中的逗號 ( ,) 是 . 的簡寫CROSS JOIN

這是建立在您的斷言之上的,即第二個查詢tags

返回 1 行tag_id

您從 a 獲得笛卡爾積CROSS JOIN,即 n*m 組合。

如果連接的兩邊返回多於一行,則它們相乘。

如果任一方均未返回行,則總體結果為無行且沒有任何反應。如果您不想要

這些效果,則一側必須返回至少一行,而另一側必須返回一行。

對於您的特定組合,您還可以使用嵌套子選擇:

INSERT INTO item_tags (item_id, tag_id)
SELECT item_id 
    , (SELECT id FROM tags WHERE name ILIKE '%hoax%') AS tag_id  -- single result!
FROM   properties
WHERE  name LIKE 'body';

***細微的差別:*這會插入從 external 返回的所有行SELECT,即使 subselect ontags沒有返回任何行,這將被轉換為NULL**fortag_id

INSERT

要一次處理大量此類插入,您將使用經過大量修改的查詢。但與上述第一個查詢相同的規則適用於兩個連接表中的基數。

INSERT INTO item_tags (item_id, tag_id)
SELECT p.item_id, t.id
FROM  (
  VALUES
     ('body',  'hoax')
   , ('body2', 'fun')
   , ('body3', 'love')
 ) AS it(item, tag)
JOIN   properties p ON p.name LIKE it.item
JOIN   tags t ON t.name ILIKE ('%' || it.tag ||'%');

你明白其中的邏輯吧?就個人而言,我稱之為“CROSS JOIN代理”。

引用自:https://dba.stackexchange.com/questions/65576