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 世纪星源

Oracle 在 left join 语句上面, 和 sql server 一样的啊, 都是标准的 SQL 语法.

上面的 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 版本下测试通过.

参考技术A 哥哥,没看见图啊,left join 就是以左面表为准,通过关联条件,将对应的数据查出来,左面表中的数据都会有,对应右面表中没有的会显示null 参考技术B 好像差不多的吧追问

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中怎么实现的主要内容,如果未能解决你的问题,请参考以下文章

通过 LEFT JOIN 优化 SQL 子查询

Oracle Left Join 导致单行子查询返回多行错误

SQL LEFT JOIN 子查询别名

MySql子查询(wherefromexists)及连接查询(left joinright joininner joinunion join)

带有子查询语法的 LEFT OUTER JOIN

资深java工程师写mysql表子查询left join导致大事务-线上事故