简体   繁体   English

Oracle SQL Self-Join:如何包括丢失的记录

[英]Oracle SQL Self-Join: How to include the missing record

I want to display the NAME and PLAN even if they are no records. 我想显示NAME和PLAN,即使它们没有记录。 I tried to use self join on this one but no luck :( 我试图在此连接上使用自我连接,但没有运气:(

script: 脚本:

    SELECT DISTINCT    A.NAME  , B.PLAN
    FROM PLAYER A  
    LEFT JOIN PLAYER B
    ON A.NAME = B.NAME 
    WHERE A.NAME IN ( 'BOGGIE', 'STEPH')
    AND  B.PLAN IN ('PLAN200' , 'PLAN999');

current result 当前结果

    NAME    PLAN
    BOOGIE  PLAN200
    STEPH   PLAN200

expected result 预期结果

    NAME    PLAN
    BOOGIE  PLAN200
    BOOGIE  
    STEPH   PLAN200
    STEPH   

TABLE

    NAME    PLAN    AMOUNT  CONTRACT
    BOGGIE  PLAN200   200      24
    STEPH   PLAN200   200      24

You can try using put your other condition in ON clause 您可以尝试将其他条件放在ON clause

SELECT DISTINCT    A.NAME  , B.PLAN
    FROM PLAYER A  
    LEFT JOIN PLAYER B
    ON A.NAME = B.NAME 
    and A.NAME IN ( 'BOGGIE', 'STEPH')
    AND  B.PLAN IN ('PLAN200' , 'PLAN999');

The problem with the query is: 查询的问题是:

A.NAME IN ( 'BOGGIE', 'STEPH') AND B.PLAN IN ('PLAN200' , 'PLAN999');

The query is putting a left join on NAME , but the records are getting further filtered after the left join has been applied. 查询将left join放在NAME ,但是在应用left join后,记录将进一步过滤。 The where clause conditions should be correctly added in left join clause. 应该在left join子句中正确添加where子句条件。

Below query should give the expected result. 下面的查询应给出预期的结果。

SELECT DISTINCT    A.NAME  , B.PLAN
FROM PLAYER A 
LEFT JOIN PLAYER B
ON A.NAME = B.NAME
AND (A.NAME IN ( 'BOGGIE', 'STEPH')
OR B.PLAN IN ('PLAN200' , 'PLAN999'));

The sample data in the question is incomplete to have the desired output; 问题中的样本数据不完整,无法获得所需的输出; please try the below. 请尝试以下。 Added two rows for BOGGIE and STEPH with null plans; 为BOGGIE和STEPH添加了两行,其中包含空计划; let us know this suffices. 让我们知道这足够了。

WITH player
     AS (SELECT 'BOGGIE' name,
                'PLAN200' plan,
                200 amount,
                24 contract
           FROM DUAL
         UNION
         SELECT 'STEPH ' name,
                'PLAN200' plan,
                200 amount,
                24 contract
           FROM DUAL
         UNION
         SELECT 'BOGGIE' name,
                NULL plan,
                NULL amount,
                NULL contract
           FROM DUAL
         UNION
         SELECT 'STEPH ' name,
                NULL plan,
                NULL amount,
                NULL contract
           FROM DUAL)
SELECT DISTINCT a.name, b.plan
  FROM player a
       LEFT OUTER JOIN player b
          ON     a.name = b.name
             AND (   a.name IN ('BOGGIE', 'STEPH')
                  OR b.plan IN ('PLAN200', 'PLAN999')) 

Output 输出量

NAME   PLAN   
------ -------
BOGGIE PLAN200
BOGGIE        
STEPH  PLAN200
STEPH 

First cross join the PLAYER with the two plans --> cross_result. 首先将两个计划-> cross_result交叉加入PLAYER。 Once you get that you would have result set as follows 一旦获得,您将获得如下结果集

cross_result
BOOGIE PLAN200
BOOGIE PLAN999
STEPH  PLAN200
STEPH  PLAN999

player
BOOGIE PLAN200
STEPH  PLAN200

After that left join cross_result with the PLAYER table 之后,将cross_result与PLAYER表连接起来

with cte
      as (SELECT 'PLAN200' as plan FROM DUAL
           UNION ALL
          SELECT 'PLAN999' as plan FROM DUAL
          )
    ,cross_result  
     as (select A.PLAYER,A.PLAN
           from cte m
           join PLAYER A
             ON A.NAME IN ( 'BOGGIE', 'STEPH')
         )
   select a.PLAYER,b.PLAN /*I have choosen b.PLAN, so for a.PLAN=PLAN99 it would display null*/
     from cross_result a
left join PLAYER b
       on a.player=b.player
      and a.plan=b.plan

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM