连接具有不同条件的同一张表的 2 个子集

Posted

技术标签:

【中文标题】连接具有不同条件的同一张表的 2 个子集【英文标题】:Joining 2 subsets of same table with different conditions 【发布时间】:2021-04-02 12:32:18 【问题描述】:
ID Timestamp type account
212 2021-01-06 14:47:35 019 ALA058748
212 2021-01-07 18:34:44 021 API305575
212 2021-01-07 22:34:48 021 XYZ565656
212 2021-01-08 00:31:25 021 API305575
212 2021-01-08 00:31:31 021 API305575
212 2021-01-08 00:34:44 020 API305575
123 2021-05-21 03:34:44 021 API305575
123 2021-05-21 05:34:44 019 API305575
123 2021-05-21 09:34:44 021 API305575
123 2021-05-21 03:34:44 020 PQR464646

我有一张像上面这样的桌子

我只需要选择那些 -

步骤 1) MINIMUM(Timestamp) 类型 = 021 的 ID --- 说 X

第 2 步)(时间戳),类型 = 020,ID 和帐户与 X 中的相同 --- Say Y

WHERE (Y-X) in minutes > 30

在此示例中 - 将仅选择 ID 212,因为对于 ID 123 ,具有 MIN(Timestamp) 的帐户,其中 type=021 具有类型=020 的帐户

谢谢

【问题讨论】:

我删除了不一致的数据库标签。请仅使用您真正使用的数据库进行标记。 您使用的是哪个 dbms? Hive/Impala SQL 【参考方案1】:

架构:

 create table t 
 (
     ID int, 
     Timestamp datetime,
     type int, 
     account varchar(50)
 );

 insert into t values(212, '2021-01-06 14:47:35', 019, 'ALA058748');
 insert into t values(212, '2021-01-07 18:34:44', 021, 'API305575');
 insert into t values(212, '2021-01-07 22:34:48', 021, 'XYZ565656');
 insert into t values(212, '2021-01-08 00:31:25', 021, 'API305575');
 insert into t values(212, '2021-01-08 00:31:31', 021, 'API305575');
 insert into t values(212, '2021-01-08 00:34:44', 020, 'API305575');
 insert into t values(123, '2021-05-21 03:34:44', 021, 'API305575');
 insert into t values(123, '2021-05-21 05:34:44', 019, 'API305575');
 insert into t values(123, '2021-05-21 09:34:44', 021, 'API305575');
 insert into t values(123, '2021-05-21 03:34:44', 020, 'PQR464646');

mysql 的查询 #1:

select id
from t
group by id
having TIMESTAMPDIFF(minute, min(case when type = '021' then timestamp end),
        min(case when type = '020' then timestamp end))>30

SQL Server 的查询 #2:

 select id
 from t
 group by id
 having datediff(minute, min(case when type = '021' then timestamp end),
         min(case when type = '020' then timestamp end))>30

输出:

id
212

db小提琴here

【讨论】:

【参考方案2】:

您可以使用聚合和过滤来做您想做的事。众所周知,日期函数依赖于数据库,因此“30 分钟”逻辑可能在您的数据库中有所不同:

select id, account
from t
group by id, account
having min(timestamp) = min(case when type = '021' then timestamp end) and
       min(timestamp) < min(case when type = '020' then timestamp end) + interval '30 minute'

【讨论】:

我也需要考虑帐户,对于需要验证时间差异的两个时间戳应该相同。 @AjinkyaPujari 。 . .如果您对 id/account 组合都需要它,那么只需将它用于 group by @GordonLinoff 你能帮我得到两个时间戳值吗? ,我可以弄清楚差异逻辑。我想加入表本身,一个实例与 min(timestamp) where type = 021 和另一个实例的 timestamp where type=020 ,加入基于ID和Account

以上是关于连接具有不同条件的同一张表的 2 个子集的主要内容,如果未能解决你的问题,请参考以下文章

oracle 连接

oracle数据库:表连接

CROSS JOIN连接用于生成两张表的笛卡尔集

oracle 多表连接查询

20161118学习笔记

用条件连接五张表的 SQL 查询