ORACLE LEFT JOIN 子查询 在SQL SERVER中可以使用如图中的子查询,ORACLE中怎么实现
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ORACLE LEFT JOIN 子查询 在SQL SERVER中可以使用如图中的子查询,ORACLE中怎么实现相关的知识,希望对你有一定的参考价值。
select a.InnerCode,a.ChangeDate,b.ChangeDate,a.SecurityAbbr
from LC_SecuChange a
left join LC_SecuChange b
on a.InnerCode = b.InnerCode
and b.ChangeDate = (select min(ChangeDate) from LC_SecuChange where InnerCode = a.InnerCode
and ChangeDate > isnull(a.ChangeDate,'1900-01-01'))
order by a.InnerCode,a.ChangeDate
结果是:世纪星源这只股票历年来简称的更改状况,第一条记录是从上市到1994-01-03是"深原野A"最后一条记录是2008-06-25至今是"世纪星源"
LC_SecuChange 表中原有记录为:
select a.InnerCode,a.ChangeDate,a.SecurityAbbr
from LC_SecuChange a
where a.InnerCode = 17
17 深原野A
17 1994-01-03 深星源A
17 1996-06-15 世纪星源
17 2003-04-16 ST 星 源
17 2003-05-12 *ST 星源
17 2004-05-18 ST 星 源
17 2006-07-31 GST星源
17 2006-10-09 ST 星 源
17 2008-06-25 世纪星源
上面的 sql
也就是 isnull(a.ChangeDate,'1900-01-01') 语句
需要修改为 NVL ( a.ChangeDate, '1900-01-01')
如果 ChangeDate 数据类型是 DATE 的, 那么
NVL ( a.ChangeDate, TO_DATE( '1900-01-01' , 'YYYY-MM-DD' ) )追问
ORA-01799:列不能外部联接子查询
ORACLE中不可以像SQL SERVER这样用
and b.ChangeDate = (select min(ChangeDate) from LC_SecuChange where InnerCode = a.InnerCode and ChangeDate > isnull(a.ChangeDate,'1900-01-01'))
SELECT
InnerCode,
ChangeDate,
LEAD(ChangeDate, 1)
OVER( PARTITION BY InnerCode
ORDER BY NVL( ChangeDate, TO_DATE('1900-01-01', 'YYYY-MM-DD' ))) AS "ChangeDate2",
SecurityAbbr
FROM
LC_SecuChange
ORDER BY
NVL( ChangeDate, TO_DATE('1900-01-01', 'YYYY-MM-DD' ));
INNERCODE CHANGEDATE ChangeDate SECURITYABBR
---------- ---------- ---------- -----------------------
17 1994-01-03 深星源A
17 1994-01-03 1996-06-15 深星源A
17 1996-06-15 2003-04-16 世纪星源
17 2003-04-16 2003-05-12 ST 星 源
17 2003-05-12 2004-05-18 *ST 星源
17 2004-05-18 2006-07-31 ST 星 源
17 2006-07-31 2006-10-09 GST星源
17 2006-10-09 2008-06-25 ST 星 源
17 2008-06-25 世纪星源
已选择9行。
Oracle 10g Express 版本下测试通过.
Oracle Left Join 导致单行子查询返回多行错误
【中文标题】Oracle Left Join 导致单行子查询返回多行错误【英文标题】:Oracle Left Join causing single-row subquery returns more than one row error 【发布时间】:2020-09-04 14:54:49 【问题描述】:不知道为什么这段代码不起作用——似乎是一个相对容易的连接。
select *
FROM VIEW_DB.VIEW1 VC0
LEFT OUTER JOIN VIEW_DB.VIEW2 VC1
ON TRIM(VC0.STRING_DATE) = TO_CHAR(VC1.CALENDAR_DAY, 'MM/DD/YYYY')
在示例中 VC0.STRING_DATE 是一个包含 varchar 数据的字段,2020 年 1 月 1 日的示例将是:“01/01/2020”(添加引号以显示空白)。
日历日是一个日期字段。
目标是在左外连接完整的情况下连接字符串日期到日期字段。使用 INNER 加入,这可以正常工作。
附加说明
VIEW1 -- 只是一个临时表的 1:1 视图。 STRING_DATE 存储为 VARCHAR(100)。在这件事上我别无选择。我们希望通过更好的 ETL 映射来消除这个问题,但目前这是我们坚持的问题。
VIEW2 -- CAL_DT 是一个 DATE 列。制作者:TRUNC(to_date('2020/01/01', 'yyyy/mm/dd') -1 + N.n) as CAL_DT
【问题讨论】:
向我们展示视图定义... 我不明白这会如何引发单行子查询返回多行错误。 关心共享列类型,如果它们是 VARCHAR2,格式?我闻到可能需要一两个 trunc()。 查询看起来没问题。错误必须在其中一个视图中。 @jarlh 我添加了更多详细信息。 【参考方案1】:转换值,但仅在一侧:
SELECT *
FROM VIEW_DB.VIEW1 VC0 LEFT OUTER JOIN
VIEW_DB.VIEW2 VC1
ON TO_DATE(VC0.STRING_DATE, 'MMM DD YYYY') = VC1.CALENDAR_DAY;
当然,这可能会产生类型转换错误。这是一件好事。您应该学习如何使用正确的数据类型存储值。而且字符串不是日期的正确数据类型。
【讨论】:
如果 CV1.CALENDAR_DAY 也有小时和秒怎么办? @BigMike:那么 CALENDAR_DAY 是一个非常糟糕的名称 :-) 太糟糕了,Oracle 没有真正的DATE
数据类型,而只有日期时间类型他们调用 DATE。
我已经更新了我的笔记——这个设计不是自愿的。我的主要问题是为什么这适用于 INNER 而不是 LEFT。这是某种 Oracle 特定问题,因为我将在 Teradata 中工作。
@ThorstenKettner 这就是为什么我更喜欢在比较时添加一个明确的 TRUNC(date_column),如果你知道时间部分总是 00:00:00,你可以跳过 trunc以上是关于ORACLE LEFT JOIN 子查询 在SQL SERVER中可以使用如图中的子查询,ORACLE中怎么实现的主要内容,如果未能解决你的问题,请参考以下文章
Oracle Left Join 导致单行子查询返回多行错误
MySql子查询(wherefromexists)及连接查询(left joinright joininner joinunion join)