根据匹配另一列标识符中所有行的列内容来选择行?

Posted

技术标签:

【中文标题】根据匹配另一列标识符中所有行的列内容来选择行?【英文标题】:Select rows based on matching a column contents across all rows within an identifier in another column? 【发布时间】:2021-10-06 19:48:59 【问题描述】:

在 Windows 10 企业版 21H1 上运行 SQL Server 14.0.2037.2

仅当该 ID 内所有行中的另一个列条目与第二个表中类似列的条目匹配时,我才尝试返回 ID,同样在特定 ID 内。 例如,

create table #F(patentid VARCHAR(8), subclass VARCHAR(3));

insert into #F values ('l','x');
insert into #F values ('l','y');
insert into #F values ('l','z');

insert into #F values ('m','x');

insert into #F values ('n','z');


create table #P(patentid VARCHAR(8), subclass VARCHAR(3));


insert into #P values ('b','x');

insert into #P values ('c','w');
insert into #P values ('c','x');
insert into #P values ('c','y');
insert into #P values ('c','z');

insert into #P values ('d','x');
insert into #P values ('d','y');
insert into #P values ('d','z');

insert into #P values ('e','x');
insert into #P values ('e','y');
insert into #P values ('e','z');

我正在尝试编写一个查询,该查询将为#F 中的每个专利ID 返回子类条目完全匹配的#P 中的所有专利ID。 #F 中的 "l" 与 #P 中的 "d" 和 "e" 匹配 [匹配的子类是 'x'、'y' 和 'z'] 以及#F中的“m”与#P中的“b”匹配[匹配的子类是“x”]

输出应该是:

l, d
l, e
m, b

代码需要高效,因为 #F 和 #P 都包含数百万行。我尝试过 Union,但它适用于整组行,并且不允许按子集匹配(即在专利 ID 内)

非常感谢任何帮助。

【问题讨论】:

这可能会有所帮助: -- 您想要的是一个联接,其中源中的项目数与联接表中的项目数匹配,并且与联接中的项目数匹配 dbfiddle.uk/… 【参考方案1】:

这是Relational Division Without Remainder 的示例,有多个除数

换句话说,您希望将#F 除以#P(在关系意义上),并且只取没有余数的结果。

解决方法很多,这里有一个

patentid 对两个表进行分区并计算窗口计数 通过subclass 将一个表与另一个表左连接,根据精确匹配计数进行过滤 按 ID 对分组 过滤掉没有匹配p.subclass 的所有f.subclass,我们使用HAVING COUNT(*) = COUNT(p.subclass) 执行此操作,因为COUNT(p.subclass) 只计算非空值。
SELECT
  f.patentid, p.patentid
FROM (
    SELECT *,
      cnt = COUNT(*) OVER (PARTITION BY f.patentid)
    FROM #F f
) f
LEFT JOIN (
    SELECT *,
      cnt = COUNT(*) OVER (PARTITION BY p.patentid)
    FROM #P p
) p ON p.cnt = f.cnt AND p.subclass = f.subclass
GROUP BY
  f.patentid, p.patentid
HAVING COUNT(*) = COUNT(p.subclass);

db<>fiddle

【讨论】:

这很棒而且效果很好。非常感谢@Charlieface!我今天学到了一些东西..(分区选择行集..)【参考方案2】:

这对您来说足够高效吗?

select f.patentId, p.patentid 
from (
    select patentId, STRING_AGG(subclass,'') WITHIN GROUP (ORDER BY subclass ASC) as class 
    from #F 
    group by patentId
) f
inner join (
    select patentId, STRING_AGG(subclass,'') WITHIN GROUP (ORDER BY subclass ASC) as class 
    from #P 
    group by patentId
) p on f.class = p.class

【讨论】:

一个很好的答案解释了它是如何工作的,除了提供工作代码。 这不起作用——这将为 m 提供多个结果,因为 x 在许多组中——您还必须检查计数(正如我在评论中所说)

以上是关于根据匹配另一列标识符中所有行的列内容来选择行?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以从第一列包含与其他文件名称匹配的标识符的文件中提取某些行?

查找并匹配列中的元素并更改另一列中相应行的值

redshift update 命令从另一列设置值,该列名是标识符

SQL 选择由 Ids 标识并由另一个表中的特定类型过滤的行列表中的所有第一项

使用按下按钮和数组行的标识来执行 segue

如果存在于列表中,则根据另一列的值选择列