带子查询的外连接 (Oracle 11g)
Outer Join with Sub-query (Oracle 11g)
我需要一个到 table 的外部连接,它受子查询的限制。但是,Oracle 正在返回
ORA-01799: a column may not be outer-joined to a sub-query
然后我尝试将外部连接推送到另一个子查询中,但由于原始子查询依赖于主 table 中的一个字段,它正在连接到,这失败了
ORA-00904: "DTL"."TRANS_DATETIME": invalid identifier
谁能建议如何解决此连接?
查询:
SELECT *
FROM header hdr
JOIN detail dtl
ON hdr.trans_number = ptd.trans_number
LEFT JOIN ( SELECT product_code
,cost_price
FROM prodcost pr
WHERE pr.last_amend_date = (SELECT MAX(pc.last_amend_date)
FROM prodcost pc
WHERE pc.product_code = pr.product_code
AND pc.last_amend_date <= trunc(dtl.trans_datetime))) p
ON ptd.product_code = p.product_code
说明
我有 header
和 detail
table 加入交易号(这实际上与问题无关,可以认为是单个 table)。然后我需要在 product_code
上离开加入 prodcost
table。但是,我必须根据 trans_datetime
之前的最新 last_amend_date
来限制它
所以detail
table是一个交易记录,有产品ID(product_code
)和交易日期(trans_datetime
)。 prodcost
table 记录了产品成本,其中包含产品 ID (product_code
) 和生效日期 (last_amend_date
)。因此,根据交易发生的时间,单个产品可能有多种成本。为了确定正确的成本,我需要 product_code
link 和 trans_datetime
之前的最近 last_amend_date
。
我知道我可以将其拆分为两个查询并 UNION
它们以提供完整的结果集。但是,如果可能的话,我宁愿避免这种情况。任何其他关于如何解决的建议将不胜感激。
这里有几个例子应该可以帮助你实现你所追求的目标(我自己编的 tables/data 因为你拒绝提供样本数据,但原则是一样的,你应该能够将其应用于您自己的查询):
示例 1(使用左连接和分析函数):
with t1 as (select 1 id, to_date('01/01/2016', 'dd/mm/yyyy') dt, 'a' val from dual union all
select 2 id, to_date('02/03/2016', 'dd/mm/yyyy') dt, 'b' val from dual union all
select 3 id, to_date('03/02/2016', 'dd/mm/yyyy') dt, 'c' val from dual union all
select 4 id, to_date('04/01/2016', 'dd/mm/yyyy') dt, 'd' val from dual),
t2 as (select 1 id, 100 val, to_date('01/12/2015', 'dd/mm/yyyy') dt from dual union all
select 1 id, 120 val, to_date('12/12/2015', 'dd/mm/yyyy') dt from dual union all
select 1 id, 130 val, to_date('04/01/2016', 'dd/mm/yyyy') dt from dual union all
select 2 id, 200 val, to_date('01/03/2016', 'dd/mm/yyyy') dt from dual union all
select 3 id, 300 val, to_date('04/03/2016', 'dd/mm/yyyy') dt from dual union all
select 3 id, 330 val, to_date('06/03/2016', 'dd/mm/yyyy') dt from dual)
-- end of mimicking two tables, t1 and t2, containing data. See SQL below:
select id,
t1_dt,
t1_val,
t2_val
from (select t1.id,
t1.dt t1_dt,
t1.val t1_val,
t2.val t2_val,
t2.dt t2_dt,
row_number() over (partition by t1.id order by t2.dt desc) rn
from t1
left outer join (select id,
val,
dt
from t2) t2 on (t1.id = t2.id and t2.dt <= t1.dt))
where rn = 1;
ID T1_DT T1_VAL T2_VAL
---------- ---------- ------ ----------
1 01/01/2016 a 120
2 02/03/2016 b 200
3 03/02/2016 c
4 04/01/2016 d
示例 2(使用标量子查询):
with t1 as (select 1 id, to_date('01/01/2016', 'dd/mm/yyyy') dt, 'a' val from dual union all
select 2 id, to_date('02/03/2016', 'dd/mm/yyyy') dt, 'b' val from dual union all
select 3 id, to_date('03/02/2016', 'dd/mm/yyyy') dt, 'c' val from dual union all
select 4 id, to_date('04/01/2016', 'dd/mm/yyyy') dt, 'd' val from dual),
t2 as (select 1 id, 100 val, to_date('01/12/2015', 'dd/mm/yyyy') dt from dual union all
select 1 id, 120 val, to_date('12/12/2015', 'dd/mm/yyyy') dt from dual union all
select 1 id, 130 val, to_date('04/01/2016', 'dd/mm/yyyy') dt from dual union all
select 2 id, 200 val, to_date('01/03/2016', 'dd/mm/yyyy') dt from dual union all
select 3 id, 300 val, to_date('04/03/2016', 'dd/mm/yyyy') dt from dual union all
select 3 id, 330 val, to_date('06/03/2016', 'dd/mm/yyyy') dt from dual)
-- end of mimicking two tables, t1 and t2, containing data. See SQL below:
select id,
dt t1_dt,
val t1_val,
(select max(val) keep (dense_rank first order by t2.dt desc) max_val
from t2
where t1.id = t2.id
and t2.dt <= t1.dt) t2_val
from t1;
ID T1_DT T1_VAL T2_VAL
---------- ---------- ------ ----------
1 01/01/2016 a 120
2 02/03/2016 b 200
3 03/02/2016 c
4 04/01/2016 d
N.B。我假设 t1.id 是唯一的。
我需要一个到 table 的外部连接,它受子查询的限制。但是,Oracle 正在返回
ORA-01799: a column may not be outer-joined to a sub-query
然后我尝试将外部连接推送到另一个子查询中,但由于原始子查询依赖于主 table 中的一个字段,它正在连接到,这失败了
ORA-00904: "DTL"."TRANS_DATETIME": invalid identifier
谁能建议如何解决此连接?
查询:
SELECT *
FROM header hdr
JOIN detail dtl
ON hdr.trans_number = ptd.trans_number
LEFT JOIN ( SELECT product_code
,cost_price
FROM prodcost pr
WHERE pr.last_amend_date = (SELECT MAX(pc.last_amend_date)
FROM prodcost pc
WHERE pc.product_code = pr.product_code
AND pc.last_amend_date <= trunc(dtl.trans_datetime))) p
ON ptd.product_code = p.product_code
说明
我有 header
和 detail
table 加入交易号(这实际上与问题无关,可以认为是单个 table)。然后我需要在 product_code
上离开加入 prodcost
table。但是,我必须根据 trans_datetime
last_amend_date
来限制它
所以detail
table是一个交易记录,有产品ID(product_code
)和交易日期(trans_datetime
)。 prodcost
table 记录了产品成本,其中包含产品 ID (product_code
) 和生效日期 (last_amend_date
)。因此,根据交易发生的时间,单个产品可能有多种成本。为了确定正确的成本,我需要 product_code
link 和 trans_datetime
之前的最近 last_amend_date
。
我知道我可以将其拆分为两个查询并 UNION
它们以提供完整的结果集。但是,如果可能的话,我宁愿避免这种情况。任何其他关于如何解决的建议将不胜感激。
这里有几个例子应该可以帮助你实现你所追求的目标(我自己编的 tables/data 因为你拒绝提供样本数据,但原则是一样的,你应该能够将其应用于您自己的查询):
示例 1(使用左连接和分析函数):
with t1 as (select 1 id, to_date('01/01/2016', 'dd/mm/yyyy') dt, 'a' val from dual union all
select 2 id, to_date('02/03/2016', 'dd/mm/yyyy') dt, 'b' val from dual union all
select 3 id, to_date('03/02/2016', 'dd/mm/yyyy') dt, 'c' val from dual union all
select 4 id, to_date('04/01/2016', 'dd/mm/yyyy') dt, 'd' val from dual),
t2 as (select 1 id, 100 val, to_date('01/12/2015', 'dd/mm/yyyy') dt from dual union all
select 1 id, 120 val, to_date('12/12/2015', 'dd/mm/yyyy') dt from dual union all
select 1 id, 130 val, to_date('04/01/2016', 'dd/mm/yyyy') dt from dual union all
select 2 id, 200 val, to_date('01/03/2016', 'dd/mm/yyyy') dt from dual union all
select 3 id, 300 val, to_date('04/03/2016', 'dd/mm/yyyy') dt from dual union all
select 3 id, 330 val, to_date('06/03/2016', 'dd/mm/yyyy') dt from dual)
-- end of mimicking two tables, t1 and t2, containing data. See SQL below:
select id,
t1_dt,
t1_val,
t2_val
from (select t1.id,
t1.dt t1_dt,
t1.val t1_val,
t2.val t2_val,
t2.dt t2_dt,
row_number() over (partition by t1.id order by t2.dt desc) rn
from t1
left outer join (select id,
val,
dt
from t2) t2 on (t1.id = t2.id and t2.dt <= t1.dt))
where rn = 1;
ID T1_DT T1_VAL T2_VAL
---------- ---------- ------ ----------
1 01/01/2016 a 120
2 02/03/2016 b 200
3 03/02/2016 c
4 04/01/2016 d
示例 2(使用标量子查询):
with t1 as (select 1 id, to_date('01/01/2016', 'dd/mm/yyyy') dt, 'a' val from dual union all
select 2 id, to_date('02/03/2016', 'dd/mm/yyyy') dt, 'b' val from dual union all
select 3 id, to_date('03/02/2016', 'dd/mm/yyyy') dt, 'c' val from dual union all
select 4 id, to_date('04/01/2016', 'dd/mm/yyyy') dt, 'd' val from dual),
t2 as (select 1 id, 100 val, to_date('01/12/2015', 'dd/mm/yyyy') dt from dual union all
select 1 id, 120 val, to_date('12/12/2015', 'dd/mm/yyyy') dt from dual union all
select 1 id, 130 val, to_date('04/01/2016', 'dd/mm/yyyy') dt from dual union all
select 2 id, 200 val, to_date('01/03/2016', 'dd/mm/yyyy') dt from dual union all
select 3 id, 300 val, to_date('04/03/2016', 'dd/mm/yyyy') dt from dual union all
select 3 id, 330 val, to_date('06/03/2016', 'dd/mm/yyyy') dt from dual)
-- end of mimicking two tables, t1 and t2, containing data. See SQL below:
select id,
dt t1_dt,
val t1_val,
(select max(val) keep (dense_rank first order by t2.dt desc) max_val
from t2
where t1.id = t2.id
and t2.dt <= t1.dt) t2_val
from t1;
ID T1_DT T1_VAL T2_VAL
---------- ---------- ------ ----------
1 01/01/2016 a 120
2 02/03/2016 b 200
3 03/02/2016 c
4 04/01/2016 d
N.B。我假设 t1.id 是唯一的。