首页 > 解决方案 > 仅当每个唯一列值不存在时才为每个唯一列值添加一行

问题描述

我有两张桌子: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

CompanyData对于每个有效的唯一公司,我想将名为“testData”的数据插入到中。所以我希望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表稍作修改,使得 'testData' 已经存在,则此查询将不再起作用。例如:

CompanyData

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

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

标签: sqlpostgresqlexistspostgresql-10

解决方案


这会像请求的那样插入行:

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'已存在行的公司。

. _ NOT IN_ CompanyData(Company, Data)_
或者使用更专业的部分索引甚至更快:

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

但特殊索引只有在您继续需要时才值得。

看:

另外:考虑 Postgres 中合法的、小写的、不带引号的标识符。看:


推荐阅读