有人可以向我解释自我加入的工作原理吗
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
每个 ItemCode
和 ItemNo
并使用 Sum()
除以原来的 Itemtotal
根据 ItemNo
和 ItemCode
。例如在 ItemCode
CT1 和 ItemNo
A
中,它的总和是 50,想将它除以 20 和 30,这是 [=14= 的原始 itemTotal
] CT1 和 ItemNo
A. 下一个不同的 ItemCode
和 ItemNo
也会发生同样的情况。另外,如果您可以提供有帮助的解释。干杯!
预期结果
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 )
我真的很困惑自连接是如何工作的,网上只有几个自连接的例子,大部分只是展示了如何在 table 中了解员工的经理。所以我有这个 table
ItemCode ItemNo ItemTotal
---------------------------------
CT1 | A | 20
CT1 | A | 30
CT2 | A | 40
CT2 | A | 10
我想 Sum()
列 ItemTotal
每个 ItemCode
和 ItemNo
并使用 Sum()
除以原来的 Itemtotal
根据 ItemNo
和 ItemCode
。例如在 ItemCode
CT1 和 ItemNo
A
中,它的总和是 50,想将它除以 20 和 30,这是 [=14= 的原始 itemTotal
] CT1 和 ItemNo
A. 下一个不同的 ItemCode
和 ItemNo
也会发生同样的情况。另外,如果您可以提供有帮助的解释。干杯!
预期结果
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 )