ORACLE特别加入

时间:2013-01-10 09:09:53

标签: sql oracle

让我试着解释一下这个场景。我有两张桌子A(列 - A1,A2,A3)& B(列 - B1,B2,B3)。我需要在A1.B2上将表A与表B连接起来。对于每个连接,表B具有一个或两个具有不同B3(X或Y)值的记录。我想编写一个查询,其中JOIN查询需要选择B3 = X的行(如果没有其他行,B3 = Y);如果存在两行(B3 = X& B3 = Y),则查询只需要选择B3 = Y的行(忽略B3 = X的行)。

让我试着给表和表格赋予一些价值。再解释一下。

Table A
********
A1   A2   A3
1    11   111
2    22   222
3    33   333
4    44   444

Table B
********
B1   B2   B3
6    1    X
7    1    Y
8    2    X
9    3    X
10   3    Y
11   4    X

Again.. JOIN is on A1.B2. The result should be as following,

JOIN Results
*************
A1   A2   A3   B1   B2   B3
1    11   111  7    1    Y
2    22   222  8    2    X
3    33   333  10   3    Y
4    44   444  11   4    X

如果你们对我的问题有任何澄清,请告诉我。

提前致谢。 瑜珈

4 个答案:

答案 0 :(得分:3)

如果您按加​​入列进行分区并按“拣配顺序”列进行排序,则可以使用ROW_NUMBER功能从表B中选择行:

SELECT b1, b2, b3,
       ROW_NUMBER() OVER (PARTITION BY b2 ORDER BY b3 DESC) as rn
  FROM b;

1 Y 1
1 X 2
2 X 1
3 Y 1
3 X 2
4 X 1

然后您可以过滤第一行,即rn=1

SELECT b1, b2, b3
  FROM (SELECT b1, b2, b3,
               ROW_NUMBER() OVER (PARTITION BY b2 ORDER BY b3 DESC) as rn
          FROM b)
 WHERE rn=1;

7  1 Y
8  2 X
10 3 Y
11 4 X

然后可以将已过滤的行连接到表a:

SELECT *
  FROM a 
  JOIN (
        SELECT b1, b2, b3
          FROM (SELECT b1, b2, b3,
                       ROW_NUMBER() OVER (PARTITION BY b2 ORDER BY b3 DESC) as rn
                  FROM b
                )
          WHERE rn=1
       ) bfilter  ON a.a1 = bfilter.b2;

1 11 111  7 1 Y
2 22 222  8 2 X
3 33 333 10 3 Y
4 44 444 11 4 X   

如果'X'和'Y'不是实际值,您可以使用ORDER语句扩展CASE子句以允许使用一般值:

 ROW_NUMBER() OVER (PARTITION BY b2 ORDER BY 
   CASE b3 WHEN 'Y' THEN 1
           WHEN 'X' THEN 2
           ...
    END ASC)

编辑:

 SELECT a1, a2, a3, b1, b2, b3
   FROM (
         SELECT a1, a2, a3, b1, b2, b3,
                ROWNUMBER() OVER (PARTITION BY a1 ORDER BY 
                   CASE WHEN a2=... AND b3=... THEN 1
                        WHEN a2=... AND b3=... THEN 2
                        ...
                   END ASC)
          FROM a JOIN b ON a.a1 = b.b2
        ) 
  WHERE rn = 1;

答案 1 :(得分:1)

您可以按如下方式使用左外连接

select A.A1, A.A2, A.A3, 
nvl(BT1.B1, BT2.B1), 
nvl(BT1.B2, BT2.B2),
nvl(BT1.B3, BT2.B3) from A 
left outer join B BT1 on A.A1 = BT1.B2 and BT1.B3 = 'Y'
left outer join B BT2 on A.A1 = BT2.B2 and BT2.B3 = 'X'

各种联接的一个很好的解释是http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

答案 2 :(得分:0)

以下是我将如何做到这一点:

  • 进行加入
  • 分组由B2
  • 取最大值(B3)

这样,只有在没有按字母顺序排列的较高值(Y)时,才能确保选择X

答案 3 :(得分:0)

使用UNION

select a.*,b.* from a,b
where a.a1=b.b2
and b.b3='Y'
union
select a.*,b.* from a,b
where a.a1=b.b2
and not exists (select bb.br from b bb where bb.b2=a.a1 and bb.b3='Y')

没有UNION

select a.*,b.* from a,b
where a.a1=b.b2
and (b.b3='Y'
or not exists (select bb.b3 from b bb where bb.b2=a.a1 and bb.b3='Y'))

这里的约束是B对于每个A的行

恰好有1或2行