仅当每个唯一列值不存在时才为它添加一行

Add a row for each unique column value only if it doesn't already exist

我有两个 table:IsCompanyValidCompanyData

IsCompanyValid:

Company   IsValid
A         TRUE
B         TRUE
C         TRUE
D         FALSE

CompanyData:

Company   Data
A         Data1
A         Data1
A         Data1
B         Data1
B         Data1
C         Data1
D         Data1

我想为每个有效的唯一公司将名为 'testData' 的数据插入 CompanyData。所以我希望 CompanyData 看起来像这样:

CompanyData:

Company   Data
A         Data1
A         Data1
A         Data1
B         Data1
B         Data1
C         Data1
D         Data1
A         testData
B         testData
C         testData

这是我写的查询:

INSERT into CompanyData (Company, Data)
SELECT
    distinct Company,
    'testData'
FROM CompanyData

-- Make sure the data we are inserting is for valid companies only
WHERE Company in
(
    select Company from IsCompanyValid
    where IsValid = true
)
AND 'testData' not in
(
    select Data from CompanyData
);

现在可以正常工作了。但是如果 CompanyData table 被稍微修改,使得 'testData' 已经存在,这个查询将不再有效。例如:

CompanyData:

Company   Data
A         Data1
A         Data1
A         Data1
B         Data1
B         Data1
C         Data1
D         Data1
A         testData

此查询将不再插入 B 和 C。我不确定如何修改我的查询以插入 B 和 C。
实际数据要大得多,所以我需要将我的解决方案推广。

这会按要求插入行:

INSERT INTO CompanyData(Company, Data)
SELECT i.Company, 'testData'::text
FROM   IsCompanyValid i
WHERE  i.IsValid 
AND    NOT EXISTS (
   SELECT FROM CompanyData d
   WHERE  d.Company = i.Company
   AND    d.Data = 'testData'
   );

跳过已存在 Data = 'testData' 行的公司。

也应该 快速 和 NULL 安全(与 NOT IN 相对),索引在 CompanyData(Company, Data).
或者使用更专业的部分索引甚至更快:

CREATE INDEX foo ON CompanyData(Company)
WHERE  Data = 'testData';

但是特殊索引只有在您一直需要它时才会付费。

参见:

  • Select rows which are not present in other table

旁白:考虑 Postgres 中合法的、小写的、不带引号的标识符。参见:

  • Are PostgreSQL column names case-sensitive?