有人可以向我解释自我加入是如何运作的

时间:2016-09-21 06:46:27

标签: sql oracle join self-join

我真的很困惑自我加入是如何工作的,只有少数在线自我加入的例子,而且大多数只是展示了如何知道表中员工的经理。所以我有这张桌子

ItemCode     ItemNo    ItemTotal
---------------------------------
CT1       |    A     |    20
CT1       |    A     |    30
CT2       |    A     |    40
CT2       |    A     |    10

我希望每个Sum()ItemTotal ItemCodeItemNo并使用Sum()将其除以原来的Itemtotal ItemNoItemCode。例如,在ItemCode CT1和ItemNo A中,它的总和为50,并希望将其除以20和30,这是itemTotal的原始ItemCode } CT1和ItemNo答。下一个不同的ItemCodeItemNo会发生同样的情况。此外,如果您能提供有用的解释。干杯!

预期结果

ItemCode       ItemNo     ItemTotal
-------------------------------------
CT1       |      A     |    0.4   ----20/50
CT1       |      A     |    0.6   ----30/50 
CT2       |      A     |    0.8
CT2       |      A     |    0.2

3 个答案:

答案 0 :(得分:3)

您只需对表进行一次扫描即可完成此操作:

with test(ItemCode, ItemNo, ItemTotal) as
(
  select 'CT1', 'A', 20 from dual union all
  select 'CT1', 'A', 30 from dual union all
  select 'CT2', 'A', 40 from dual union all
  select 'CT2', 'A', 10 from dual 
)
select ItemCode, ItemNo,
       ItemTotal / sum(ItemTotal) over ( partition by ItemCode,ItemNo) 
from test

为了完整性,如果您想要一个带连接的解决方案,您可以使用:

select ItemCode,ItemNo, t1.ItemTotal / sum(t2.ItemTotal)
from test t1
     inner join test t2 
       using(ItemCode,ItemNo)
group by ItemCode, ItemNo, t1.ItemTotal  

然而,这两种方法有不同的表现;加入解决方案的计划:

----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |     8 |   336 |     8  (25)| 00:00:01 |
|   1 |  HASH GROUP BY      |      |     8 |   336 |     8  (25)| 00:00:01 |
|*  2 |   HASH JOIN         |      |     8 |   336 |     7  (15)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| TEST |     4 |    84 |     3   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| TEST |     4 |    84 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------

和单扫描解决方案:

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     4 |    84 |     4  (25)| 00:00:01 |
|   1 |  WINDOW SORT       |      |     4 |    84 |     4  (25)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| TEST |     4 |    84 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

答案 1 :(得分:1)

Oracle可能有一些奇特的功能来做到这一点。但由于我不太了解Oracle,我会做一个简单的相关子查询答案:

select
    ItemCode,
    ItemNo,
    ItemTotal * 1.0 / (
        select SUM(ItemTotal)
        from tablename t2
        where t2.ItemNo = t1.ItemNo
    )
from tablename t1

也许你想做

cast(ItemTotal * 1.0 / (
    select SUM(ItemTotal)
    from tablename t2
    where t2.ItemNo = t1.ItemNo
) as decimal(1,1))

答案 2 :(得分:1)

以下是Oracle功能强大的方式:

EXCEPTION: Error: Uncaught (in promise): TypeError: push.on is not a function

请注意,这可能比以下更强大:

select ItemCode,
       ItemNo,
       ratio_to_report(ItemTotal) over ( partition by ItemCode,ItemNo) 
from   my_table;

...因为它隐含地将除以零错误并且返回null,否则将需要:

ItemTotal / sum(ItemTotal) over ( partition by ItemCode,ItemNo)