SQL 子查询计算
SQL subqueries calculations
我有这个 table:
╔═════╤═══════╤═══════╗
║ ID │ Group │ Value ║
╠═════╪═══════╪═══════╣
║ ID1 │ 1 │ 10 ║
╟─────┼───────┼───────╢
║ ID2 │ 1 │ 5 ║
╟─────┼───────┼───────╢
║ ID2 │ 1 │ 4 ║
╟─────┼───────┼───────╢
║ ID2 │ 1 │ 6 ║
╟─────┼───────┼───────╢
║ ID1 │ 2 │ 1 ║
╟─────┼───────┼───────╢
║ ID2 │ 2 │ 7 ║
╟─────┼───────┼───────╢
║ ID2 │ 2 │ 8 ║
╟─────┼───────┼───────╢
║ ID2 │ 2 │ 3 ║
╟─────┼───────┼───────╢
║ ID3 │ 3 │ 6 ║
╟─────┼───────┼───────╢
║ ID2 │ 3 │ 4 ║
╟─────┼───────┼───────╢
║ ID2 │ 3 │ 1 ║
╟─────┼───────┼───────╢
║ ID2 │ 3 │ 9 ║
╚═════╧═══════╧═══════╝
我想执行以下操作:
- 查找 ID = ID1 的所有组
- 提取与ID = ID1属于同一组的ID2的平均值
ID1只存在于Group1和Group2中。因此 ID2 的平均值
第 1 组 = (5+4+6)/3 = 5
和第 2 组 = (7+8+3)/3 = 6
- 计算每组 ID1 值相对于 ID2 平均值的百分比。
第 1 组 = (10*100%)/5 = 200%
第 2 组 = (1*100%)/6 = 16%
我知道如何分别执行这些步骤,但我不知道如何在第二个查询中使用第一个查询(组)的列表。
Search_Item = 'ID1'
Select Group FROM MyTable WHERE ID = 'ID1'
-> Return 1 和 2
Select AVG(Value) FROM MyTable WHERE ID = 'ID2' AND Group = '1'
Select AVG(Value) FROM MyTable WHERE ID = 'ID2' AND Group = '2'
如有任何帮助,我们将不胜感激。
你可以这样做:
SELECT t.group,NVL(avg(s.value),0),(MAX(t.value)*100/NVL(avg(s.value),1)) as Perc
FROM(
SELECT group,max(value) as value FROM MyTable WHERE ID = 'ID1' group by group) t
LEFT OUTER JOIN Mytable s
ON(t.group = s.group and s.ID = 'ID2')
GROUP BY t.group
您可以像这样使用单个 table 扫描来完成此操作:
SELECT "GROUP",
100 * SUM( CASE id WHEN 'ID1' THEN value END )
/ AVG( CASE id WHEN 'ID2' THEN value END )
AS Percentage
FROM MyTable
GROUP BY "GROUP"
HAVING COUNT( CASE id WHEN 'ID1' THEN 1 END ) > 0;
输出
GROUP PERCENTAGE
----- ----------
1 200
2 16.6666667
如果您只想要只有一行 ID
为 ID1
的组,则将最后一行更改为:
HAVING COUNT( CASE id WHEN 'ID1' THEN 1 END ) = 1;
您可能有一个包含 ID1
行的组,并且 ID2
行的总和为零(如果您允许零值或负值)——查询将抛出ORA-01476: divisor is equal to zero
异常。如果你想防止这种情况发生,那么你可以使用:
SELECT "GROUP",
100 * SUM( CASE id WHEN 'ID1' THEN value END )
/ CASE AVG( CASE id WHEN 'ID2' THEN value END )
WHEN 0 THEN NULL
ELSE AVG( CASE id WHEN 'ID2' THEN value END )
END
AS Percentage
...
我有这个 table:
╔═════╤═══════╤═══════╗
║ ID │ Group │ Value ║
╠═════╪═══════╪═══════╣
║ ID1 │ 1 │ 10 ║
╟─────┼───────┼───────╢
║ ID2 │ 1 │ 5 ║
╟─────┼───────┼───────╢
║ ID2 │ 1 │ 4 ║
╟─────┼───────┼───────╢
║ ID2 │ 1 │ 6 ║
╟─────┼───────┼───────╢
║ ID1 │ 2 │ 1 ║
╟─────┼───────┼───────╢
║ ID2 │ 2 │ 7 ║
╟─────┼───────┼───────╢
║ ID2 │ 2 │ 8 ║
╟─────┼───────┼───────╢
║ ID2 │ 2 │ 3 ║
╟─────┼───────┼───────╢
║ ID3 │ 3 │ 6 ║
╟─────┼───────┼───────╢
║ ID2 │ 3 │ 4 ║
╟─────┼───────┼───────╢
║ ID2 │ 3 │ 1 ║
╟─────┼───────┼───────╢
║ ID2 │ 3 │ 9 ║
╚═════╧═══════╧═══════╝
我想执行以下操作:
- 查找 ID = ID1 的所有组
- 提取与ID = ID1属于同一组的ID2的平均值
ID1只存在于Group1和Group2中。因此 ID2 的平均值 第 1 组 = (5+4+6)/3 = 5
和第 2 组 = (7+8+3)/3 = 6
- 计算每组 ID1 值相对于 ID2 平均值的百分比。
第 1 组 = (10*100%)/5 = 200%
第 2 组 = (1*100%)/6 = 16%
我知道如何分别执行这些步骤,但我不知道如何在第二个查询中使用第一个查询(组)的列表。
Search_Item = 'ID1'
Select Group FROM MyTable WHERE ID = 'ID1'
-> Return 1 和 2
Select AVG(Value) FROM MyTable WHERE ID = 'ID2' AND Group = '1'
Select AVG(Value) FROM MyTable WHERE ID = 'ID2' AND Group = '2'
如有任何帮助,我们将不胜感激。
你可以这样做:
SELECT t.group,NVL(avg(s.value),0),(MAX(t.value)*100/NVL(avg(s.value),1)) as Perc
FROM(
SELECT group,max(value) as value FROM MyTable WHERE ID = 'ID1' group by group) t
LEFT OUTER JOIN Mytable s
ON(t.group = s.group and s.ID = 'ID2')
GROUP BY t.group
您可以像这样使用单个 table 扫描来完成此操作:
SELECT "GROUP",
100 * SUM( CASE id WHEN 'ID1' THEN value END )
/ AVG( CASE id WHEN 'ID2' THEN value END )
AS Percentage
FROM MyTable
GROUP BY "GROUP"
HAVING COUNT( CASE id WHEN 'ID1' THEN 1 END ) > 0;
输出
GROUP PERCENTAGE
----- ----------
1 200
2 16.6666667
如果您只想要只有一行 ID
为 ID1
的组,则将最后一行更改为:
HAVING COUNT( CASE id WHEN 'ID1' THEN 1 END ) = 1;
您可能有一个包含 ID1
行的组,并且 ID2
行的总和为零(如果您允许零值或负值)——查询将抛出ORA-01476: divisor is equal to zero
异常。如果你想防止这种情况发生,那么你可以使用:
SELECT "GROUP",
100 * SUM( CASE id WHEN 'ID1' THEN value END )
/ CASE AVG( CASE id WHEN 'ID2' THEN value END )
WHEN 0 THEN NULL
ELSE AVG( CASE id WHEN 'ID2' THEN value END )
END
AS Percentage
...