Sql Oracle中带日期的左外联接和必要子查询

Sql Oracle中带日期的左外联接和必要子查询,sql,oracle,subquery,left-join,Sql,Oracle,Subquery,Left Join,我正在努力处理一个左外连接,其中右部分(可能包含null)不显示值。我认为这种情况被称为隐式内部连接。原因是子查询不返回空值,而是不返回我想要的右边部分的值 (此问题与此不同,因为需要一个子查询来查找最长日期。) 以下是一个简化的示例: Table Contracts: customer_id, status Table Values: customer_id, value_code, value, begin_date 我想显示状态为'active'的所有客户,以及某个值代码的最新值,比如

我正在努力处理一个左外连接,其中右部分(可能包含null)不显示值。我认为这种情况被称为隐式内部连接。原因是子查询不返回空值,而是不返回我想要的右边部分的值

(此问题与此不同,因为需要一个子查询来查找最长日期。)

以下是一个简化的示例:

Table Contracts:
customer_id, status

Table Values:
customer_id, value_code, value, begin_date
我想显示状态为'active'的所有客户,以及某个值代码的最新值,比如说'volume'。有更多的值_代码,并且这些值具有特定的有效日期。也可以没有值_代码,但我希望右侧为NULL

下面是我试图做的:

SELECT * FROM CONTRACTS C
LEFT JOIN VALUES V ON C.CUSTOMER_ID = V.CUSTOMER_ID
                      AND VALUE_CODE = 'VOLUME'
WHERE C.STATUS = 'ACTIVE'
     AND V.BEGIN_DATE = (
                         SELECT MAX(BEGIN_DATE) FROM VALUES V2 
                         WHERE V2.CUSTOMER_ID = V.CUSTOMER_ID
                         AND V2.VALUE_CODE = 'VOLUME'
                         )
我不能将子查询放在join子句中,Oracle不会接受。另一方面,我的子查询使所有没有代码为“volume”的值条目的行都被省略。我想要的是让value=NULL,所有客户都在左边


谢谢你的帮助

首先过滤
行,然后过滤
左连接

SELECT *
FROM   CONTRACTS C
       LEFT JOIN
       ( SELECT *
         FROM   (
           SELECT V.*,
                  ROW_NUMBER() OVER ( PARTITION BY CUSTOMER_ID ORDER BY BEGIN_DATE DESC )
                    AS rn
           FROM   VALUES V
         )
         WHERE rn = 1
       ) V
ON     ( C.CUSTOMER_ID = V.CUSTOMER_ID
         AND VALUE_CODE = 'VOLUME' )
WHERE C.STATUS = 'ACTIVE'

首先过滤
行,然后过滤
左连接

SELECT *
FROM   CONTRACTS C
       LEFT JOIN
       ( SELECT *
         FROM   (
           SELECT V.*,
                  ROW_NUMBER() OVER ( PARTITION BY CUSTOMER_ID ORDER BY BEGIN_DATE DESC )
                    AS rn
           FROM   VALUES V
         )
         WHERE rn = 1
       ) V
ON     ( C.CUSTOMER_ID = V.CUSTOMER_ID
         AND VALUE_CODE = 'VOLUME' )
WHERE C.STATUS = 'ACTIVE'

正如MT0所建议的,使用分区和按行号排序会有所帮助。为了我的目的,我只需要在分区中包含value_代码

所以这个查询最终达到了我的目的:

SELECT *
FROM   CONTRACTS C
       LEFT JOIN
       ( SELECT *
         FROM   (
           SELECT V.*,
                  ROW_NUMBER() OVER ( PARTITION BY CUSTOMER_ID, VALUE_CODE ORDER BY BEGIN_DATE DESC )
                    AS rn
           FROM   VALUES V
         )
         WHERE rn = 1
       ) V
ON     ( C.CUSTOMER_ID = V.CUSTOMER_ID
         AND VALUE_CODE = 'VOLUME' )
WHERE C.STATUS = 'ACTIVE'

正如MT0所建议的,使用分区和按行号排序会有所帮助。为了我的目的,我只需要在分区中包含value_代码

所以这个查询最终达到了我的目的:

SELECT *
FROM   CONTRACTS C
       LEFT JOIN
       ( SELECT *
         FROM   (
           SELECT V.*,
                  ROW_NUMBER() OVER ( PARTITION BY CUSTOMER_ID, VALUE_CODE ORDER BY BEGIN_DATE DESC )
                    AS rn
           FROM   VALUES V
         )
         WHERE rn = 1
       ) V
ON     ( C.CUSTOMER_ID = V.CUSTOMER_ID
         AND VALUE_CODE = 'VOLUME' )
WHERE C.STATUS = 'ACTIVE'

感谢您提供的分区技巧(几乎从未使用过)。为了让它工作,我不得不稍微改变一下。因为我只想要代码为“volume”的值,所以我不得不说“按客户id划分,按开始日期描述划分值\u代码顺序”JayChistnAh我简要地考虑了<代码> ValueEXCODION/CODE >,但是在列之前没有一个别名将它与一个表关联,所以我不知道它是来自<代码>值< /> >还是<代码>合同表。是的,如果它位于
VALUES
中,则将其添加到
partitionby
子句中。感谢您提供的分区技巧(几乎从未使用过)。为了让它工作,我不得不稍微改变一下。因为我只想要代码为“volume”的值,所以我不得不说“按客户id划分,按开始日期描述划分值\u代码顺序”JayChistnAh我简要地考虑了<代码> ValueEXCODION/CODE >,但是在列之前没有一个别名将它与一个表关联,所以我不知道它是来自<代码>值< /> >还是<代码>合同表。是的,如果它位于
VALUES
中,则将其添加到
PARTITION BY
子句中。您应该记住并正确使用这些术语。分区可能意味着表分区,与使用分析函数的分区子句相比,这是一个完全不同的特性。分区可能意味着表分区,与使用analyticfunctions.Hi的Partitioning子句相比,这是一个完全不同的特性。这是一个常见问题。请总是用谷歌搜索错误信息,对你的问题/问题/目标的许多清晰、简洁和具体的版本/措辞,有或没有你的特定字符串/名称,以及“site:stackoverflow.com”&标记并阅读许多答案。将发现的相关关键字添加到搜索中。如果你找不到答案,就发布,使用1个变体搜索作为标签的标题和关键字。请参见文本上方的向下投票箭头鼠标。当您确实有非重复代码问题要发布时,请阅读并执行操作。了解左联接返回的内容:内部联接行加上由null扩展的不匹配左表行。始终知道作为左连接的一部分,您需要什么样的内部连接。一个WHERE或INTERNAL ON,在左联接ON删除任何由NULL扩展的行后,要求右表列不为NULL,即只保留内部联接行,即“将左联接转换为内部联接”。你有。其他问题可能重复,具体到哪里。我把我的问题翻译成了最简单的描述。另外,这个问题与我通过搜索发现的略有不同(我确实搜索了很多次)。无法通过将where子句中的条件置于“on”子句中来解决此问题,因为需要一个子查询。1。不管这段代码还有什么问题,它都有这个问题。2.“甲骨文不会接受”是什么意思?3.4.在给定输入的情况下,您不会解释您想要什么输出。描述得足够清楚,有人可以带着正确的代码离开和回来。这就是你要问的。一旦你明白了,这几乎肯定是一个常见问题。5.请看我的下一条评论。这是一个常见问题。请总是用谷歌搜索错误信息,对你的问题/问题/目标的许多清晰、简洁和具体的版本/措辞,有或没有你的特定字符串/名称,以及“site:stackoverflow.com”&标记并阅读许多答案。将发现的相关关键字添加到搜索中。如果你找不到答案,就发布,使用1个变体搜索作为标签的标题和关键字。请参见文本上方的向下投票箭头鼠标。当您确实有非重复代码问题要发布时,请阅读并执行操作。了解左联接返回的内容:内部联接行加上由null扩展的不匹配左表行。始终知道作为左连接的一部分,您需要什么样的内部连接。一个WHERE或INTERNAL ON,在左联接ON删除任何由NULL扩展的行后,要求右表列不为NULL,即只保留内部联接行,即“将左联接转换为内部联接”。你有。其他问题可能重复,具体到哪里。我把我的问题翻译成了最简单的描述。另外,这个问题与我通过搜索发现的略有不同(我确实搜索了很多次)。无法通过将where子句中的条件置于“on”子句中来解决此问题,因为需要一个子查询。1。不管这段代码还有什么问题,它都有这个问题。2.什么是“Orac”