【问题标题】:Finding all occurences of a column value that do not exist in other table in SQL查找所有出现在 SQL 中的其他表中不存在的列值
【发布时间】:2020-05-27 05:27:40
【问题描述】:

我的问题如下:

我有两个表:第一个表有两列(person_idaccount_ids 列)。 Account_ids 列存在逗号分隔的帐户 ID:

Person_ID    Account_ids
-----------------------------------------------------------------
  123        000000grVA6AM,000016ILMhAO, 000000ihi4MAQ, 000000TF5MAQQ,000000TF5MAHZ
  124        000000frVA6AM,000016ILMhAO
  125        000000frVA6BC,000024ILMhJZ, 000000frXC6A,000024YTMhA

第二张表包含有关 person_id 的详细信息

Person_ID   Account_ID      Account_Name
----------------------------------------
  123       000000grVA6AM     Name1
  123       000016ILMhAO      Name2
  123       000000ihi4MAQ     Name3
  123       000000TF5MAQQ     Name4
  123       000000TF5MAHZ     Name5
  124       000016ILMhAO      Name2
  124       000000TF5MAHZ     Name5
  124       000000frVA6AM     Name6
  124       000024ILMhAO      Name7
  124       000000frVA7XZ     Name8
  125       000000frVA6BC     Name9 
  125       000024ILMhJZ      Name10
  125       000000frXC6A      Name11
  125       000024YTMhA       Name12
  125       000024IXThJY      Name13

我想为每个person_id 找到所有account_ids,而这些Person_ID 没有出现在表1 中。例如,从上面的例子中,答案应该是:

Person_ID   Account_ID      Account_Name
-----------------------------------------

   124      000000TF5MAHZ     Name5
   124      000024ILMhAO      Name7
   124      000000frVA7XZ     Name8
   125      000024IXThJY      Name13

我该怎么做?

我试图应用 not like 子句,但后来我不明白如何在表 1 中拆分逗号分隔值。请帮忙!

谢谢!

更新:

提供临时表创建查询,以便更容易测试:

CREATE TEMP table persons
( person_id int, account_id varchar(20), account_name varchar(10))

insert into persons values
 (123,       '000000grVA6AM',     'Name1');
 insert into persons values
  (123,       '000016ILMhAO',      'Name2');
  insert into persons values
  (123,       '000000ihi4MAQ',     'Name3');
  insert into persons values
  (123,       '000000TF5MAQQ',     'Name4');
  insert into persons values
  (123,       '000000TF5MAHZ',     'Name5');
  insert into persons values
  (124,      '000016ILMhAO',      'Name2');
  insert into persons values
  (124,       '000000TF5MAHZ',     'Name5');
  insert into persons values
  (124,      '000000frVA6AM',     'Name6');
  insert into persons values
  (124,       '000024ILMhAO',      'Name7');
  insert into persons values
  (124,       '000000frVA7XZ',     'Name8');
  insert into persons values
  (125,       '000000frVA6BC',     'Name9');
  insert into persons values 
  (125,       '000024ILMhJZ',      'Name10');
  insert into persons values
  (125,       '000000frXC6A',      'Name11');
  insert into persons values
  (125,       '000024YTMhA',       'Name12';
  insert into persons values
  (125,       '000024IXThJY'      'Name13');

对于帐户表:

CREATE TEMP table accounts
(person_id int, account_ids varchar(100))

insert into accounts values
(123,        '000000grVA6AM,000016ILMhAO, 000000ihi4MAQ, 000000TF5MAQQ,000000TF5MAHZ');
insert into accounts values
  (124,        '000000frVA6AM,000016ILMhAO');
insert into accounts values
  (125,        '000000frVA6BC,000024ILMhJZ, 000000frXC6A,000024YTMhA');

【问题讨论】:

  • 您的 SQL Server 版本是多少?
  • Amazon Redshift 还是 Microsoft SQL Server?这是两种截然不同的数据库产品
  • @user10096621 。 . .我删除了不一致的数据库标签。具有您在网站上的经验的人应该知道如何使用您实际使用的数据库标记问题。
  • 抱歉,不知道我如何标记 SQL Server,它实际上是 Redshift。

标签: sql amazon-redshift


【解决方案1】:

我们可以试试:

SELECT p.Person_ID, p.Account_ID, p.Account_Name
FROM persons p
WHERE NOT EXISTS (SELECT 1 FROM accounts a
                  WHERE ',' || a.Account_ids || ',' LIKE '%,' || p.AccountID || ',%');

请注意,将您的帐户作为 CSV 数据存储在单列中并不是最佳的数据库设计,因为此类数据未规范化。为了编写您想要的查询,我们必须执行字符串 olympics 来检查 CSV 字符串中是否存在每个帐户。如果这些帐户都在单独的记录中,我们的任务会更容易。

编辑:

如果您的 CSV 帐户数据中确实包含空格,请使用替换进行比较,首先将其删除:

WHERE NOT EXISTS (SELECT 1 FROM accounts a
                  WHERE ',' || REPLACE(a.Account_ids, ' ', '')  || ','
                        LIKE '%,' || p.AccountID || ',%');

【讨论】:

  • 对,我同意,但是我们从用户输入字段中获得逗号分隔的列,用户手动输入一些信息,我们从中提取帐户 ID 并将其存储到列中。每个用户可以输入的帐户 ID 的数量是不同的。即一个用户可以输入 2 个帐户 ID,而另一个用户可以输入 3 个等等。
  • 您能否解释一下您在不存在子句中所做的事情。谢谢!
  • 是否会找到(或不找到,视情况而定)包含逗号周围空格的 Account_id?
  • @AlwaysLearning 我假设空格是复制错误,但我已经更新了我的答案以处理这种极端情况。
  • @TimBiegeleisen 我添加了一些空格,因为此数据将成为用户输入字段,我希望包括用户在输入值时可以使用的所有可能情况。
【解决方案2】:

如果您使用的是 SQL Server 2016 或更高版本,则可以使用 STRING_SPLIT() 函数来分隔独立测试的 CSV 值,例如:

select b.*
from (
  select Person_ID, Account_ID
  from dbo.Table2
  except
  select Person_ID, trim(Value)
  from dbo.Table1
  cross apply string_split(Account_ids, N',')
) a
join dbo.Table2 b on b.Person_ID=a.Person_ID and b.Account_ID=a.Account_ID

注意 trim(Value) 会丢弃 Account_ids 列中帐户 ID 周围的任何空格字符,这需要 SQL Server 2017 或更高版本,您可以在早期版本上使用 ltrim(rtrim(Value))

【讨论】:

  • 你怎么知道 OP 正在使用 SQL Server?
  • 我们没有。但是他们在其中添加了垃圾邮件标签sql-server
猜你喜欢
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
  • 2014-02-14
  • 2018-07-13
  • 1970-01-01
  • 1970-01-01
  • 2019-03-28
  • 2014-09-09
相关资源
最近更新 更多