将一个表的列中的数据与另一个表中的同一列进行比较

Posted

技术标签:

【中文标题】将一个表的列中的数据与另一个表中的同一列进行比较【英文标题】:Comparing data in a column of one table with the same column in another table 【发布时间】:2014-06-11 08:59:43 【问题描述】:

我分别有两张表 temp 和 md。有一个名为 uri_stem 的字段,其中有一些我想从 temp 中省略而不是从 md 中省略的细节。如果 md 中有类似的模式,我需要进行比较,以便能够比较某些模式并将它们从 temp 中删除。

现在我正在使用此代码删除与我想省略的模式相似的数据,但我想要一些能够比较 md 表中的模式的方法,而不是我对每个模式进行硬编码。希望解释足够清楚。

FROM 
  spfmtr01.tbl_1c_apps_log_temp 
where 
 uri_stem not like '%.js' and 
 uri_stem not like '%.css' and 
 uri_stem not like  '%.gif' 
 and uri_stem not like '%.png' 
 and uri_stem not like '%.html' 
 and uri_stem not like '%.jpg' 
 and uri_stem not like '%.jpeg' 
 and uri_stem not like '%.ico' 
 and uri_stem not like '%.htm' 
 and uri_stem not  like '%.pdf' 
 and uri_stem not  like '%.Png' 
 and uri_stem not  like '%.PNG'

【问题讨论】:

This 应该可以帮助你部分 【参考方案1】:

这个例子是基于我在评论中提到的answer。

SQLFiddle

样本数据:

drop table if exists a, b;
create table a (testedstr varchar);
create table b (condstr varchar);

insert into a values 
   ('aa.aa.jpg'),
   ('aa.aa.bjpg'), -- no match
   ('aa.aa.jxpg'), -- no match
   ('aa.aa.jPg'), 
   ('aa.aa.aico'), -- no match
   ('aa.aa.ico'), 
   ('bb.cc.dd.icox'), -- no match
   ('bb.cc.dd.cco');  -- no match

insert into b values ('jpg'), ('ico');

解释:

在表a 中有我们想要测试的字符串(存储在testedstr 列中) 在表 b 中,我们有想要用作测试表达式的字符串(存储在 condstr 列中)

SQL:

with cte as (select '\.(' || string_agg(condstr,'|') || ')$' condstr from b)

select * from a, cte where testedstr !~* condstr;

解释:

在第一行中,我们将所有想要测试的模式聚合到一个字符串中;结果,我们将得到jpg|ico 字符串(聚合为单行)。 在第二行中,我们将测试表与我们的测试表达式(来自第一行)交叉连接,并使用正则表达式来执行测试。 最后的正则表达式看起来像\.(jpg|ico)$

对于旧版本,您应该使用@Bohemian 提供的答案。对于我的示例数据,它看起来像(针对多个可能的点进行了调整)(SQLFiddle:

select 
  *
from 
  a
where 
  lower(reverse(split_part(reverse(testedstr),'.',1))) 
    not in (select lower(condstr) from b)

没有reverse函数(SQLFiddle):

select 
  *,
  lower(split_part(testedstr,'.',length(testedstr)- length(replace(testedstr,'.','')) + 1)) as extension
from 
  a
where 
  lower(split_part(testedstr,'.',length(testedstr)- length(replace(testedstr,'.','')) + 1)) not in (select lower(condstr) from b)

【讨论】:

@user3455309 和上面写的一样,你检查过SQLFiddle上的例子吗? 您好,感谢您的帮助,但我们使用的 Postgresql 版本非常低。 8.2 我猜所以它不支持 cte。此代码还有其他替代方法吗? @user3455309 选项 1:升级,选项 2:查看我编辑的答案。 谢谢。虽然升级听起来是一个不错的选择,但不幸的是它不在我手中。我尝试了您的查询,但它抛出错误“函数反向(字符变化)不存在”。 @user3455309 是的,我的错,古代版本没有reverse功能。查看我更新的答案,这次我检查了 8.2 是否支持所有功能【参考方案2】:

首先让我们将许多条件重构为一个:

where lower(substring(uri_stem from '[^.]+$')) not in ('js', 'css', 'gif', 'png', 'html', 'jpg', 'jpeg', 'ico', 'htm', 'pdf')

在这种形式中,很容易看出如何选择值列表而不是编码:

where lower(substring(uri_stem from '[^.]+$')) not in (
    select lower(somecolumn) from sometable)

注意使用 lower() 以避免处理大小写变体的问题。

您也可以将其编码为连接:

select t1.*
from mytable t1
left join sometable t2
    on lower(somecolumn) = lower(split_part(uri_stem, '.', 2))
where t2.somecolumn is null -- filter out matches

【讨论】:

这假设字符串中只有一个点。使用select lower(reverse(split_part(reverse('aaa.bbb.cCc'),'.',1)))之类的东西来获取字符串中最后一个点之后的部分字符串不是更好吗? 正是我想提到的。字符串有多个点。这是一个需要比较的字符串示例。 /Core/Scripts/jquery.flipCounter.1.2.js @TomasGreif 是的,你是对的,但有一个更简单的解决方法:你可以使用正则表达式 substring(uri_stem from '[^.]+$') 提取所有尾随非点字符 - 请参阅编辑 @user3455309 我的第一个剪辑不适合多个点,但请参阅编辑以了解如何使用正则表达式 substring(uri_stem from '[^.]+$') 提取所有尾随非点字符,它适用于任意数量的点(不包括点)

以上是关于将一个表的列中的数据与另一个表中的同一列进行比较的主要内容,如果未能解决你的问题,请参考以下文章

如何根据与另一个表中的值的比较来更新列

基于公共列将数据框与另一列中的列连接起来

将表中的列与 hive 中另一个表的列进行比较

选择表中的列与另一个表中的列不同的数据

有没有办法将数据帧的一列中的所有行与另一个数据帧的另一列(火花)中的所有行进行比较?

如果列值 id 与另一个表中的 ID 描述匹配,则在指定列中插入数据(规范化形式)