有人可以向我解释自我加入的工作原理吗

Can someone explain to me how self join works

我真的很困惑自连接是如何工作的,网上只有几个自连接的例子,大部分只是展示了如何在 table 中了解员工的经理。所以我有这个 table

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,这是 [=14= 的原始 itemTotal ] CT1 和 ItemNo A. 下一个不同的 ItemCodeItemNo 也会发生同样的情况。另外,如果您可以提供有帮助的解释。干杯!

预期结果

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

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))

您只需扫描一次 table:

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 |
---------------------------------------------------------------------------

这是 Oracle 奇特的功能方式:

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

请注意,这可以说比以下更可靠:

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

... 因为它隐含地捕获除以零错误和 returns null,否则需要:

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