简体   繁体   English

2 个条件下的 Oracle SQL 连接列

[英]Oracle SQL Join columns on 2 conditions

I tried to search forums for my scenario but could not find anything remotely similar.我试图为我的场景搜索论坛,但找不到任何类似的东西。 So here goes my long winded explanation : I have 3 tables - order_fact , session_fact and orderline.所以这是我冗长的解释:我有 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');

As can be seen from above order_fact and session_fact tables are connected by cookie and session id.从上面可以看出 order_fact 和 session_fact 表是通过 cookie 和 session id 连接的。 The request is to get these columns : ORDER_NO, MARKETING_VENDOR, REFERRAL_TYPE, OL_REF from the above 3 tables.请求是从上述 3 个表中获取这些列:ORDER_NO、MARKETING_VENDOR、REFERRAL_TYPE、OL_REF。

I have written the JOIN query :我已经编写了 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);

Here is the sticky situation for me :这是我的棘手情况:

  1. Get the data in session_fact table for a cookie_id in order_fact for timestamp of not more than 7 days before the order_timestamp.获取 session_fact 表中 order_fact 中 cookie_id 的数据,时间戳不超过 order_timestamp 之前的 7 天。 For example - order_no 78345-20210411 was placed on 11-APR-2021 18:37:07.例如 - order_no 78345-20210411 被放置在 11-APR-2021 18:37:07。 Using the cookie id of that order I get all rows in session_fact till 11-APR - 7 days = 4-APR.使用该订单的 cookie id,我得到 session_fact 中的所有行,直到 11-APR - 7 days = 4-APR。 So 3rd and 1st Apr data cannot be considered.所以不能考虑 4 月 3 日和 1 日的数据。 This has been taken care in my query.这已在我的查询中得到照顾。 But I wanted to mention why I had the additional AND clauses in the 1st JOIN ON condition.但我想提一下为什么我在第一个 JOIN ON 条件中有额外的 AND 子句。

  2. From the data got in point 1 above do not consider those records where REFERRAL_TYPE = 'D' and MARKETING_VENDOR = '-1'.从上面第 1 点获得的数据不考虑那些 REFERRAL_TYPE = 'D' 和 MARKETING_VENDOR = '-1' 的记录。 'S' and '-1' can be considered and so is 'R' and '-1'.可以考虑“S”和“-1”,“R”和“-1”也是如此。 Basically any values can be considered as long as its NOT 'D' and '-1'.基本上任何值都可以被考虑,只要它不是“D”和“-1”。 And select the record whose timestamp is closest to the order_timestamp in table order_fact.并在order_fact表中选择时间戳最接近order_timestamp的记录。 Now this is where it gets tricky - if there are no records of past 7 days where combo of REFERRAL_TYPE and MARKETING_VENDOR is NOT 'D' and '-1' then join the tables order_fact and session_fact on both cookie_id and session_id and fetch the values.现在这就是棘手的地方 - 如果过去 7 天没有记录 REFERRAL_TYPE 和 MARKETING_VENDOR 的组合不是“D”和“-1”,那么在 cookie_id 和 session_id 上加入表 order_fact 和 session_fact 并获取值。

  3. Join tables order_fact and orderline ON ORDER_NO and OL_NBR = 1. This also has been taken care in my join query.联接表 order_fact 和 orderline ON ORDER_NO 和 OL_NBR = 1。这在我的联接查询中也已注意。

So my only problem is getting the JOIN between session_fact and order_fact on the 2 different conditions mentioned in point 2. Can this be done by SQL?所以我唯一的问题是在第 2 点中提到的 2 个不同条件下获取 session_fact 和 order_fact 之间的 JOIN。这可以通过 SQL 完成吗? The Tech Lead of my team asked me to write a PL/SQL block.我团队的技术主管让我写一个 PL/SQL 块。 I did that because the original request was to add MARKETING_VENDOR, REFERRAL_TYPE, OL_REF columns in order_fact table and get the values from their respective tables.我这样做是因为最初的请求是在 order_fact 表中添加 MARKETING_VENDOR、REFERRAL_TYPE、OL_REF 列并从它们各自的表中获取值。 I cannot help but feel this can be done by SQL using CASE.我不禁觉得这可以通过 SQL 使用 CASE 来完成。 Or am I wrong?还是我错了? If anyone could please help me with this query I will be grateful.如果有人可以帮助我解决这个问题,我将不胜感激。

Edit : Adding the result data set编辑:添加结果数据集

在此处输入图片说明

Edit : Any kind soul to help me out?编辑:任何善良的灵魂来帮助我? 🙂 I take it it's not possible in a SQL statement. 🙂 我认为在 SQL 语句中是不可能的。

And select the record whose timestamp is closest to the order_timestamp in table order_fact并在order_fact表中选择时间戳最接近order_timestamp的记录

From your description looks like you just need Top 1 record by session_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)
;

Result:结果:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM