Oracle SQL 在 2 个条件下连接列

Posted

技术标签:

【中文标题】Oracle SQL 在 2 个条件下连接列【英文标题】:Oracle SQL Join columns on 2 conditions 【发布时间】:2021-07-25 20:36:04 【问题描述】:

我尝试在论坛中搜索我的场景,但找不到任何类似的东西。所以这是我冗长的解释:我有 3 个表 - order_fact 、 session_fact 和 orderline。

create table order_fact (order_no varchar2(20), order_timestamp date, cookie_id number, session_id number);

insert into order_fact values ('69857-20210329', to_date('29-MAR-2021 10:11:58', 'DD-MON-YYYY HH24:MI:SS'), 827678, 79853421);
insert into order_fact values ('78345-20210411', to_date('11-APR-2021 18:37:07', 'DD-MON-YYYY HH24:MI:SS'), 569834, 84886798);
insert into order_fact values ('79678-20210519', to_date('19-MAY-2021 20:51:34', 'DD-MON-YYYY HH24:MI:SS'), 589623, 89556782);
insert into order_fact values ('78759-20210411', to_date('11-APR-2021 09:46:52', 'DD-MON-YYYY HH24:MI:SS'), 685213, 77549823);

create table session_fact (cookie_id number, session_id number, session_timestamp date, marketing_vendor varchar2(30) , referral_type VARCHAR2(2) );

insert into session_fact values (827678, 79853421, to_date('29-MAR-2021 09:47:36', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (827678, 79853378, to_date('28-MAR-2021 12:47:36', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (827678, 79853313, to_date('24-MAR-2021 13:23:36', 'DD-MON-YYYY HH24:MI:SS'), 'Naaptol', 'S');
insert into session_fact values (827678, 79853254, to_date('23-MAR-2021 14:39:56', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (569834, 84886798, to_date('11-APR-2021 14:41:44', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (569834, 84886735, to_date('10-APR-2021 11:03:44', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (569834, 84886687, to_date('08-APR-2021 17:26:49', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (569834, 84886659, to_date('03-APR-2021 11:03:44', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (569834, 84886497, to_date('01-APR-2021 07:59:08', 'DD-MON-YYYY HH24:MI:SS'), 'Google', 'R');
insert into session_fact values (685213, 77549823, to_date('11-APR-2021 09:07:34', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (685213, 77549786, to_date('09-APR-2021 20:51:34', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (685213, 77549589, to_date('07-APR-2021 14:11:57', 'DD-MON-YYYY HH24:MI:SS'), 'FabShopping', 'D');
insert into session_fact values (685213, 77548356, to_date('03-APR-2021 15:38:42', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (589623, 89556782, to_date('19-MAY-2021 16:46:52', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (589623, 89556512, to_date('18-MAY-2021 09:46:52', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (589623, 89556477, to_date('13-MAY-2021 18:34:29', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');
insert into session_fact values (589623, 89556348, to_date('10-MAY-2021 16:13:49', 'DD-MON-YYYY HH24:MI:SS'), '-1', 'D');

create table orderline (order_no varchar2(20), ol_nbr number, ol_ref varchar2(5));

insert into orderline values ('78345-20210411', 0, '-2');
insert into orderline values ('78345-20210411', 1, 'HV3');
insert into orderline values ('78345-20210411', 2, 'HV3');
insert into orderline values ('78759-20210411', 0, '-2');
insert into orderline values ('78759-20210411', 1, 'PS5');
insert into orderline values ('78759-20210411', 2, 'PS5');
insert into orderline values ('78759-20210411', 3, 'PS5');
insert into orderline values ('79678-20210519', 0, '-2');
insert into orderline values ('79678-20210519', 1, 'NPT');
insert into orderline values ('79678-20210519', 2, 'NPT');
insert into orderline values ('69857-20210329', 0, '-2');
insert into orderline values ('69857-20210329', 1, 'HV3');
insert into orderline values ('69857-20210329', 2, 'HV3');
insert into orderline values ('69857-20210329', 3, 'HV3');

从上面可以看出 order_fact 和 session_fact 表是通过 cookie 和 session id 连接的。请求是从上述 3 个表中获取这些列:ORDER_NO, MARKETING_VENDOR, REFERRAL_TYPE, OL_REF。

我已经编写了 JOIN 查询:

select a.ORDER_NO, b.MARKETING_VENDOR,
b.REFERRAL_TYPE, c.OL_REF 
FROM order_fact a 
INNER JOIN session_fact b
ON (a.cookie_id = b.COOKIE_ID AND 
b.session_timestamp < a.order_timestamp AND 
b.session_timestamp > a.order_timestamp-7)
INNER JOIN orderline c ON 
(a.ORDER_NO = c.ORDER_NO AND c.OL_NBR = 1);

这对我来说是棘手的情况:

    为 order_fact 中的 cookie_id 获取 session_fact 表中的数据,以获取 order_timestamp 之前不超过 7 天的时间戳。例如 - order_no 78345-20210411 被放置在 11-APR-2021 18:37:07。使用该订单的 cookie id,我得到 session_fact 中的所有行,直到 11-APR - 7 days = 4-APR。因此,不能考虑 4 月 3 日和 1 日的数据。这已在我的查询中得到照顾。但我想提一下为什么我在第一个 JOIN ON 条件中有额外的 AND 子句。

    根据上面第 1 点得到的数据,不考虑那些 REFERRAL_TYPE = 'D' 和 MARKETING_VENDOR = '-1' 的记录。可以考虑“S”和“-1”,“R”和“-1”也是如此。基本上可以考虑任何值,只要它不是“D”和“-1”。并在 order_fact 表中选择时间戳与 order_timestamp 最接近的记录。现在这是变得棘手的地方 - 如果过去 7 天没有记录,其中 REFERRAL_TYPE 和 MARKETING_VENDOR 的组合不是“D”和“-1”,则在 cookie_id 和 session_id 上加入表 order_fact 和 session_fact 并获取值。

    在 ORDER_NO 和 OL_NBR = 1 上连接表 order_fact 和 orderline。这在我的连接查询中也得到了注意。

所以我唯一的问题是在第 2 点中提到的 2 个不同条件下获取 session_fact 和 order_fact 之间的 JOIN。这可以通过 SQL 完成吗?我团队的技术主管让我编写一个 PL/SQL 块。我这样做是因为最初的请求是在 order_fact 表中添加 MARKETING_VENDOR、REFERRAL_TYPE、OL_REF 列并从它们各自的表中获取值。我不禁觉得这可以通过使用 CASE 的 SQL 来完成。还是我错了?如果有人可以帮助我解决这个问题,我将不胜感激。

编辑:添加结果数据集

编辑:有好心人来帮助我吗? ???我认为这在 SQL 语句中是不可能的。

【问题讨论】:

问题中的示例数据和所需结果作为文本表将非常有助于解释您要做什么。 当然,戈登!我已经分享了示例数据。我将从 excel 中添加结果片段。 我猜SQL不可能。 【参考方案1】:

并选择timestamp最接近order_fact表中order_timestamp的记录

从您的描述看来,您只需要 session_timestamp 的前 1 条记录:

with
 step1 as (
   SELECT 
       a.ORDER_NO
      ,a.order_timestamp
      ,c.MARKETING_VENDOR
      ,c.REFERRAL_TYPE
      ,c.session_timestamp
   FROM order_fact a 
   cross apply (
       select *
       from session_fact b
       where a.cookie_id = b.COOKIE_ID 
         and (REFERRAL_TYPE,MARKETING_VENDOR) not in (('D','-1'))
         AND b.session_timestamp < a.order_timestamp 
         --AND b.session_timestamp > a.order_timestamp-7
       order by b.session_timestamp desc
       fetch first 1 rows only
   ) c
)
select
   s.*
  ,o.OL_REF 
FROM 
   step1 s
   JOIN orderline o 
        ON (s.ORDER_NO = o.ORDER_NO AND o.OL_NBR = 1)
;

结果:

ORDER_NO       ORDER_TIMESTAMP     MARKETING_VENDOR REFERRAL_TYPE SESSION_TIMESTAMP   OL_REF
-------------- ------------------- ---------------- ------------- ------------------- ------
78345-20210411 2021-04-11 18:37:07 Google           R             2021-04-01 07:59:08 HV3
78759-20210411 2021-04-11 09:46:52 FabShopping      D             2021-04-07 14:11:57 PS5
69857-20210329 2021-03-29 10:11:58 Naaptol          S             2021-03-24 13:23:36 HV3

【讨论】:

运行查询时出现 ORA-00905:缺少关键字错误。是交叉申请还是交叉加入? @Arty155 你的预言机版本是多少? Oracle 11g 11.2.0.4.0

以上是关于Oracle SQL 在 2 个条件下连接列的主要内容,如果未能解决你的问题,请参考以下文章

在 Oracle DBMS 中的多个列上使用过滤条件连接表

带有连接的 Oracle SQL 更新列

oracle数据库的连接

菜鸟请教sql问题

如果第一个条件失败,则在具有较少条件的另一列上进行 SQL 连接

oracle 多表连接查询