Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL外部联接:";“部分空”-通缉犯_Sql_Database_Oracle_Left Join_Outer Join - Fatal编程技术网

SQL外部联接:";“部分空”-通缉犯

SQL外部联接:";“部分空”-通缉犯,sql,database,oracle,left-join,outer-join,Sql,Database,Oracle,Left Join,Outer Join,我正在寻找一种归档以下内容的方法: 想象一下表A、B: A: B: 现在看看下面的SQL语句和结果(我使用的是Oracle 11,但MSSQL应该是相同的): 从(A.aID=B.bID)上的左侧外部联接B中选择A.*,B.* 从(A.aID=B.bID和A.aID2=B.bID2)上的左侧外部联接B中选择A.*,B.* 到目前为止还不错 我正在寻找一份声明(尽可能简单),它让我得到以下信息: 组合代码:从左侧外部联接B上选择A.*,B.*(A.aID=B.bID和A.aID2=B.bID2保持

我正在寻找一种归档以下内容的方法:

想象一下表A、B:

A: B: 现在看看下面的SQL语句和结果(我使用的是Oracle 11,但MSSQL应该是相同的):

从(A.aID=B.bID)上的左侧外部联接B中选择A.*,B.* 从(A.aID=B.bID和A.aID2=B.bID2)上的左侧外部联接B中选择A.*,B.* 到目前为止还不错

我正在寻找一份声明(尽可能简单),它让我得到以下信息:

组合代码:从左侧外部联接B上选择A.*,B.*(A.aID=B.bID和A.aID2=B.bID2保持匹配列) 有没有办法只使用连接而不反复使用自连接来获得这种行为(保持匹配部分、NULL不匹配“ON”子句和所有值列的部分)

如果没有像“保持匹配COLS”这样的keyworld,你会建议什么方法? 再选择?自联接

谢谢,
Bumma

我不认为您会找到一个简单的解决方案,这里有一些东西可以在您的数据集上运行,但不美观也不高效

create table A ( aID int, aID2 int, avalue char(3) )
create table B ( bID int, bID2 int, bvalue char(3) )

insert into A VALUES (1  , 10  , 'abc')
insert into A VALUES (2  , 20  , 'def')
insert into A VALUES (3  , 30  , 'ghi')
insert into A VALUES (4  , 40  , 'jkl')


insert into B VALUES (1  , 10  , 'mno')
insert into B VALUES (20 , 20  , 'pqr')
insert into B VALUES (3  , 1   , 'stu')

select distinct
    A.*,
    COALESCE(B1.bID,B2.bID) as bID,
    COALESCE(B1.bID2,B3.bID2) as BID2,
    B1.bvalue
from A
left outer join 
    B B1
on 
    A.aID = B1.bID 
AND 
    A.aID2 = B1.bID2
left outer join 
    B B2
on 
    A.aID = B2.bID 
left outer join 
    B B3
on 
    A.aID2 = B3.bID2


aID, aID2, avalue, bID , bID2, bvalue
=====================================
1  , 10  , 'abc' , 1   , 10  , 'mno'  
2  , 20  , 'def' , NULL, 20  , NULL
3  , 30  , 'ghi' , 3   , NULL, NULL
4  , 40  , 'jkl' , NULL, NULL, NULL

不完全是自连接,但没有更好的,我希望看到一个更好的解决方案,并了解需求。

我不认为您会找到一个简单的解决方案,这里有一些东西可以在您的数据集上使用,但不美观也不高效

create table A ( aID int, aID2 int, avalue char(3) )
create table B ( bID int, bID2 int, bvalue char(3) )

insert into A VALUES (1  , 10  , 'abc')
insert into A VALUES (2  , 20  , 'def')
insert into A VALUES (3  , 30  , 'ghi')
insert into A VALUES (4  , 40  , 'jkl')


insert into B VALUES (1  , 10  , 'mno')
insert into B VALUES (20 , 20  , 'pqr')
insert into B VALUES (3  , 1   , 'stu')

select distinct
    A.*,
    COALESCE(B1.bID,B2.bID) as bID,
    COALESCE(B1.bID2,B3.bID2) as BID2,
    B1.bvalue
from A
left outer join 
    B B1
on 
    A.aID = B1.bID 
AND 
    A.aID2 = B1.bID2
left outer join 
    B B2
on 
    A.aID = B2.bID 
left outer join 
    B B3
on 
    A.aID2 = B3.bID2


aID, aID2, avalue, bID , bID2, bvalue
=====================================
1  , 10  , 'abc' , 1   , 10  , 'mno'  
2  , 20  , 'def' , NULL, 20  , NULL
3  , 30  , 'ghi' , 3   , NULL, NULL
4  , 40  , 'jkl' , NULL, NULL, NULL

不完全是自联接,但也不是更好,我希望看到更好的解决方案,并了解需求。

在Id或Id2上联接,然后在select子句中选择性地取消结果

设置测试表和数据:

set null 'NULL'
create table a (aId number
    , aId2 number
    , aValue varchar2(4));
insert into a values (1, 10, 'abc');
insert into a values (2, 20, 'def');
insert into a values (3, 30, 'ghi');
insert into a values (4, 40, 'jkl');
create table b (bId number
    , bId2 number
    , bValue varchar2(4));
insert into b values (1, 10, 'mno');
insert into b values (20, 20, 'pqr');
insert into b values (3, 1, 'stu');
commit;
查询:

select A.*
    , case when A.aId = B.bId then B.bId end as bId
    , case when A.aId2 = B.bID2 then B.bId2 end as bId2
    , case when A.aId = B.bId 
        and A.aId2 = B.bId2 then bValue end as bValue
from A
left outer join B on A.aID = B.bId or A.aId2 = B.bId2;
结果:

       AID       AID2 AVAL        BID       BID2 BVAL
---------- ---------- ---- ---------- ---------- ----
         1         10 abc           1         10 mno
         2         20 def  NULL               20 NULL
         3         30 ghi           3 NULL       NULL
         4         40 jkl  NULL       NULL       NULL
aID aID2    avalue    bID     bID2     bvalue
1   10      abc         1      10       mno       
2   20      def         NULL   20       NULL
3   30      ghi         3      NULL     NULL
4   40      jkl         NULL   NULL     NULL

在Id或Id2上联接,然后在select子句中有选择地将结果置空

设置测试表和数据:

set null 'NULL'
create table a (aId number
    , aId2 number
    , aValue varchar2(4));
insert into a values (1, 10, 'abc');
insert into a values (2, 20, 'def');
insert into a values (3, 30, 'ghi');
insert into a values (4, 40, 'jkl');
create table b (bId number
    , bId2 number
    , bValue varchar2(4));
insert into b values (1, 10, 'mno');
insert into b values (20, 20, 'pqr');
insert into b values (3, 1, 'stu');
commit;
查询:

select A.*
    , case when A.aId = B.bId then B.bId end as bId
    , case when A.aId2 = B.bID2 then B.bId2 end as bId2
    , case when A.aId = B.bId 
        and A.aId2 = B.bId2 then bValue end as bValue
from A
left outer join B on A.aID = B.bId or A.aId2 = B.bId2;
结果:

       AID       AID2 AVAL        BID       BID2 BVAL
---------- ---------- ---- ---------- ---------- ----
         1         10 abc           1         10 mno
         2         20 def  NULL               20 NULL
         3         30 ghi           3 NULL       NULL
         4         40 jkl  NULL       NULL       NULL
aID aID2    avalue    bID     bID2     bvalue
1   10      abc         1      10       mno       
2   20      def         NULL   20       NULL
3   30      ghi         3      NULL     NULL
4   40      jkl         NULL   NULL     NULL

不确定为什么不能使用/不希望使用自联接,但以下是一个版本:

SELECT  a.aID,
    a.aID2,
    a.avalue,
    b1.bID,
    b2.bID2,
    CASE WHEN b1.bID = b2.bID AND b1.bID2 = b2.bID2 THEN b1.bvalue ELSE NULL END as bvalue
FROM A  a
LEFT OUTER JOIN B b1
    ON (a.aID = b1.bID) 
LEFT OUTER JOIN B b2
    ON (a.aID2 = b2.bID2)
结果:

       AID       AID2 AVAL        BID       BID2 BVAL
---------- ---------- ---- ---------- ---------- ----
         1         10 abc           1         10 mno
         2         20 def  NULL               20 NULL
         3         30 ghi           3 NULL       NULL
         4         40 jkl  NULL       NULL       NULL
aID aID2    avalue    bID     bID2     bvalue
1   10      abc         1      10       mno       
2   20      def         NULL   20       NULL
3   30      ghi         3      NULL     NULL
4   40      jkl         NULL   NULL     NULL

不确定为什么不能使用/不希望使用自联接,但以下是一个版本:

SELECT  a.aID,
    a.aID2,
    a.avalue,
    b1.bID,
    b2.bID2,
    CASE WHEN b1.bID = b2.bID AND b1.bID2 = b2.bID2 THEN b1.bvalue ELSE NULL END as bvalue
FROM A  a
LEFT OUTER JOIN B b1
    ON (a.aID = b1.bID) 
LEFT OUTER JOIN B b2
    ON (a.aID2 = b2.bID2)
结果:

       AID       AID2 AVAL        BID       BID2 BVAL
---------- ---------- ---- ---------- ---------- ----
         1         10 abc           1         10 mno
         2         20 def  NULL               20 NULL
         3         30 ghi           3 NULL       NULL
         4         40 jkl  NULL       NULL       NULL
aID aID2    avalue    bID     bID2     bvalue
1   10      abc         1      10       mno       
2   20      def         NULL   20       NULL
3   30      ghi         3      NULL     NULL
4   40      jkl         NULL   NULL     NULL

为了便于编写(因此也便于维护),我建议您避免外部联接,而是将所需的四个子集联合起来

SELECT A.*, B.* FROM A INNER JOIN B ON (A.aID = B.bID AND A.aID2 = B.bID2)
UNION
SELECT A.*, NULL, NULL, NULL
  FROM A 
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM B 
                    WHERE (A.aID = B.bID)
                  )
       AND NOT EXISTS (
                       SELECT * 
                         FROM B 
                        WHERE (A.aID2 = B.bID2)
                      )
UNION
SELECT A.*, B.bID, NULL, NULL
  FROM A INNER JOIN B ON (A.aID = B.bID)
       AND NOT EXISTS (
                       SELECT * 
                         FROM B 
                        WHERE (A.aID2 = B.bID2)
                      )
UNION
SELECT A.*, NULL, B.bID2, NULL
  FROM A INNER JOIN B ON (A.aID2 = B.bID2)
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM B 
                    WHERE (A.aID = B.bID)
                  );

这种方法的优点是使用关系运算符join、semi-difference和union,允许那些非关系的
NULL
值(外部联接被明确设计为生成这些值)轻松地替换为实际的默认值。

为了使这更易于编写(并因此维护),我建议您避免外部联接,而是将所需的四个子集合并

SELECT A.*, B.* FROM A INNER JOIN B ON (A.aID = B.bID AND A.aID2 = B.bID2)
UNION
SELECT A.*, NULL, NULL, NULL
  FROM A 
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM B 
                    WHERE (A.aID = B.bID)
                  )
       AND NOT EXISTS (
                       SELECT * 
                         FROM B 
                        WHERE (A.aID2 = B.bID2)
                      )
UNION
SELECT A.*, B.bID, NULL, NULL
  FROM A INNER JOIN B ON (A.aID = B.bID)
       AND NOT EXISTS (
                       SELECT * 
                         FROM B 
                        WHERE (A.aID2 = B.bID2)
                      )
UNION
SELECT A.*, NULL, B.bID2, NULL
  FROM A INNER JOIN B ON (A.aID2 = B.bID2)
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM B 
                    WHERE (A.aID = B.bID)
                  );

这种方法的优点是使用关系运算符join、semi-difference和union,允许那些非关系的
NULL
值(外部联接专门用于生成)轻松替换为实际的默认值。

如果Id或Id2不匹配,则不会将bValue返回为NULL。请参见预期结果的第2行和第3行。我同意,要求是不同的,最好有更多的上下文。如果Id或Id2不匹配,则不会将bValue返回为null。请参见预期结果的第2行和第3行。我同意,要求是不同的,最好有更多的上下文。因为我对Stackoverflow比较陌生,我不知道更好的problemspecification应该属于哪里。我把它写在我的帖子的回复里。感谢Bullaas,我对Stackoverflow还比较陌生,我不知道更好的问题规范应该属于哪里。我把它写在我的帖子的回复里。谢谢你