2017-03-23 7 views
1

私は4つの一意のフィールドを持つテーブルを新しく作成しました:nsnslugpart_nomfg_skuです。PostgreSQLは複数のカラムを挿入して無視します

私はこの表に約を挿入しようとしています。行数が繰り返される複数の表から200万行。

ので、主な問題は、この場合にはinsert ignoreをエミュレートする方法を...

のですか?

複数の列に基づいて異なるかどうかを選択するか、何をお勧めしますか?ここで

は私が Partテーブル

SELECT "PartOld".id, 
    "PartOld"."PartNo", 
    "PartOld"."Manufacturer", 
    "PartOld"."Slug", 
    "PartOld"."Description", 
    "PartOld"."NSN", 
    NULL::numeric AS price, 
    "PartOld".name, 
    NULL::character varying AS mfg_sku 
    FROM "PartOld" 
UNION 
SELECT part_item.id, 
    NULL::character varying AS "PartNo", 
    part_item.manufacturer AS "Manufacturer", 
    NULL::character varying AS "Slug", 
    part_item.details AS "Description", 
    part_item.msn AS "NSN", 
    NULL::numeric AS price, 
    part_item.name, 
    part_item.mfg_sku 
    FROM part_item_fetched part_item 

に挿入するデータであり、ここでPartテーブルです。

DROP TABLE IF EXISTS "electronic_parts"."Part"; 
CREATE TABLE "electronic_parts"."Part" (
    "id" int4 NOT NULL DEFAULT nextval('"Part_id_seq"'::regclass), 
    "part_no" varchar COLLATE "default", 
    "manufacturer" varchar COLLATE "default", 
    "description" text COLLATE "default", 
    "slug" varchar COLLATE "default", 
    "nsn" varchar COLLATE "default", 
    "price" numeric, 
    "name" varchar COLLATE "default", 
    "mfg_sku" varchar COLLATE "default" 
) 
WITH (OIDS=FALSE); 
ALTER TABLE "electronic_parts"."Part" OWNER TO "root"; 

-- ---------------------------- 
-- Primary key structure for table Part 
-- ---------------------------- 
ALTER TABLE "electronic_parts"."Part" ADD PRIMARY KEY ("id") NOT DEFERRABLE INITIALLY IMMEDIATE; 

-- ---------------------------- 
-- Indexes structure for table Part 
-- ---------------------------- 
CREATE UNIQUE INDEX "part_u1" ON "electronic_parts"."Part" USING btree(part_no COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST); 
CREATE UNIQUE INDEX "part_u2" ON "electronic_parts"."Part" USING btree(nsn COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST); 
CREATE UNIQUE INDEX "part_u3" ON "electronic_parts"."Part" USING btree(mfg_sku COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST); 
+0

あなたのpostgresのバージョンを指定してください。 –

+0

@VaoTsun latest – demonoid

+0

「ON CONFLICT DO NOTHING」とは別に、入力に重複が含まれる可能性がありますか?テーブルの列は1つずつユニークなので、単一のUNION、DISTINCT、DISTINCT ONのいずれもフィルタリングに役立ちません。それはあなたの問題ですか? – pozs

答えて

0

使用

INSERT INTO ... 
    (SELECT ...) 
ON CONFLICT DO NOTHING; 

これは9.5以降で利用可能となっている、the documentationを参照してください。

0

あなたは(NOT EXISTS()またはLEFT JOIN + IS NULLでtipically)anti joinsであなたの入力をフィルタリングすることができます

WITH data AS (
    -- your query here 
    SELECT ... 
    UNION ALL ... 
), 
conflicting_ids AS (
    SELECT id  FROM data GROUP BY id  HAVING COUNT(*) > 1 
), 
conflicting_part_nos AS (
    SELECT part_no FROM data GROUP BY part_no HAVING COUNT(*) > 1 
), 
conflicting_nsns AS (
    SELECT nsn  FROM data GROUP BY nsn  HAVING COUNT(*) > 1 
), 
conflicting_mfg_skus AS (
    SELECT mfg_sku FROM data GROUP BY mfg_sku HAVING COUNT(*) > 1 
) 
INSERT INTO table_name (column_names) 
SELECT d.* 
FROM data d 
WHERE NOT EXISTS(SELECT 1 FROM conflicting_ids a  WHERE a.id = d.id) 
AND NOT EXISTS(SELECT 1 FROM conflicting_part_nos a WHERE a.part_no = d.part_no) 
AND NOT EXISTS(SELECT 1 FROM conflicting_nsns a  WHERE a.nsn = d.nsn) 
AND NOT EXISTS(SELECT 1 FROM conflicting_mfg_skus a WHERE a.mfg_sku = d.mfg_sku) 
ON CONFLICT DO NOTHING 

ノートを:それは主キーであるため、idは、あまりにもユニークです。また、競合する行は別々にチェックされるため、UNIONは必要ありません。 UNION ALLを使用すると、やや効率的です。

+0

挿入しようとしている 'd'のすべてのレコードが同じ'a'からの記録 – Gary

+0

@Garyええ、同じ正確な行を除外すべき条件は除外されました。しかし、主キーはクエリの一部であるため、一意の列を最初に「カウント」する方が簡単になります。 – pozs

関連する問題