[英]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 :这是我的棘手情况:
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 子句。
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 并获取值。
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.