การคำนวณเปอร์เซ็นต์ของแถวเหนือผลรวมทั้งหมด


13

ขอโทษสำหรับชื่อที่ไม่ดีฉันไม่แน่ใจว่าชื่อเรื่องนี้จะเป็นอะไรดี

นี่คือข้อมูลที่ฉันกำลังทำงานกับ (มุมมองแบบง่าย) ของข้อมูลนี้

Agent    |  Commission     
---------|------------
Smith    |    100
Neo      |    200
Morpheus |    300

ฉันต้องการคำนวณอัตราร้อยละของค่าคอมมิชชั่นทั้งหมดซึ่งแต่ละตัวแทนมีหน้าที่รับผิดชอบ

ดังนั้นสำหรับ Agent Smith เปอร์เซ็นต์จะถูกคำนวณเป็น (Agent Smith's commission / Sum(commission)*100

ดังนั้นข้อมูลที่คาดหวังของฉันจะเป็น

Agent    |  Commission   |  % Commission    
---------|---------------|---------------
Smith    |    100        |     17
Neo      |    200        |     33
Morpheus |    300        |     50

ฉันมีฟังก์ชั่นคืนค่าคอมมิชชั่นสำหรับแต่ละตัวแทน (Commission/Sum(Commission))*100ฉันมีฟังก์ชั่นอื่นกลับเป็นร้อยละ ปัญหาคือSum(commission)ได้รับการคำนวณสำหรับแต่ละแถวและทุกครั้งที่แบบสอบถามนี้จะถูกเรียกใช้บน Data Warehouse ชุดข้อมูลจะค่อนข้างใหญ่ (ปัจจุบันอยู่ภายใต้ 2000 ระเบียน) และค่อนข้างเป็นวิธีที่ไม่ดี (IMO) )

มีวิธีการที่Sum(Commission)ไม่มีการคำนวณสำหรับทุกแถวที่ถูกดึงข้อมูลหรือไม่?

ฉันกำลังคิดอะไรบางอย่างในบรรทัดของแบบสอบถาม 2 ส่วนส่วนแรกจะดึงข้อมูลsum(commission)เป็นตัวแปร / ชนิดของแพคเกจและส่วนที่สองจะอ้างอิงค่าที่คำนวณล่วงหน้านี้ แต่ฉันไม่แน่ใจว่าฉันจะทำสิ่งนี้ได้อย่างไร

ฉันถูก จำกัด ให้ใช้ SQL และฉันกำลังรันบน Oracle 10g R2


ไม่เห็นได้ชัดว่าเป็นคำถาม DBA (บางทีถ้าเป็นพื้นที่ทำงานแทนที่จะเป็นพนักงานขาย?) - น่าจะอยู่ใน Stack Overflow
ออกุสตุส

คำตอบ:


23

คุณกำลังหาanalytical function อัตราส่วน _to_report

select 
  agent,
  round(ratio_to_report(commission) over ()*100) "% Comm."
from  
  commissions;

เยี่ยมมากไม่รู้เรื่องนี้ขอบคุณ!
Sathyajith Bhat

9

ในการส่งคืนเอเจนต์ทั้งหมดด้วยค่าคอมมิชชั่นและเปอร์เซ็นต์ค่าคอมมิชชันให้ใช้ฟังก์ชันการวิเคราะห์โดยไม่มีประโยคการวิเคราะห์เพื่อให้พาร์ติชันอยู่เหนือตารางทั้งหมด:

SELECT Agent, commission, 100* commission / (SUM(commission) OVER ()) "% Commission" 
FROM commissions;

เมื่อฉันเรียนรู้จากRené Nyffenegger (+1) ฟังก์ชัน ratio_to_report จะทำให้ไวยากรณ์นี้แน่น

การใช้แพคเกจเพื่อเก็บค่าคอมมิชชั่น SUM จะเกี่ยวข้องกับ PL / SQL ซึ่งคุณได้แยกออกโดยเฉพาะโดยระบุว่าคุณต้องการโซลูชัน SQL แต่เนื่องจากคุณใช้ฟังก์ชั่นอยู่แล้ว หากเป็นกรณีนี้โซลูชันแพ็คเกจอาจช่วยได้ แต่ขึ้นอยู่กับการทำงานของแอปพลิเคชันของคุณ

เมื่อเซสชั่นของคุณถูกสร้างขึ้นครั้งแรกและเรียกใช้ฟังก์ชั่นในแพคเกจเพื่อรับค่าคอมมิชชั่นจะมีการโทรไปยังคอนสตรัคเตอร์แพ็คเกจโดยปริยายซึ่งอาจได้รับผลรวมและเก็บไว้ จากนั้นคุณสามารถอ้างอิงผลรวมที่เก็บไว้ในฟังก์ชันรับค่าคอมมิชชั่นของคุณและมันจะต้องทำผลรวมเพียงครั้งเดียว แน่นอนทันทีที่คุณเรียกใช้ฟังก์ชันจากเซสชันที่แตกต่างกันผลรวมจะถูกคำนวณอีกครั้ง นอกจากนี้การเรียกใช้ฟังก์ชันสำหรับทุกเอเจนต์จะมีประสิทธิภาพน้อยกว่าการเรียกคำสั่ง SQL หนึ่งคำสำหรับเอเจนต์ทั้งหมดหากแอปพลิเคชันของคุณสามารถออกแบบในลักษณะนั้นได้

คุณอาจต้องการพิจารณาเปลี่ยนฟังก์ชั่นของคุณเป็นโพรซีเดอร์ที่ส่งคืนเคอร์เซอร์สำหรับเคียวรีด้านบนหรืออาจมีฟังก์ชั่นที่ส่งคืนผลลัพธ์ของเคียวรีเป็นชุดผลลัพธ์แบบ pipelined

ข้อมูลตัวอย่าง:

create table commissions (Agent Varchar2(100), Commission Number(3));
insert into commissions values ('Smith',100);
insert into commissions values ('Neo',200);
insert into commissions values ('Morpheus',300);

5

คุณสามารถลองใช้แบบสอบถามต่อไปนี้ผลรวม (คอมมิชชั่น) จะถูกคำนวณเพียงครั้งเดียว:

WITH TOTAL_COMMISSION AS 
(SELECT SUM(COMMISSION) AS TOTAL FROM AGENTS)
SELECT A.AGENT_NAME, A.COMMISSION, ((A.COMMISSION/T.TOTAL)*100) AS "% COMMISSION"
FROM AGENTS A, TOTAL_COMMISSION T;

ใช้งานได้และส่งคืนข้อมูลที่ถูกต้อง แต่มีประสิทธิภาพน้อยกว่าฟังก์ชั่นการวิเคราะห์ที่สแกนหนึ่งตารางเต็มแทนที่จะเป็นสอง (สมมติว่าไม่มีดัชนี)
Leigh Riffel

1
@Leigh ~ มันจะทำยังไงในการส่งครั้งเดียวเนื่องจากวิธีแมนนวลต้องผ่านสองรอบ? ฉันไม่เห็นว่าคอมพิวเตอร์สามารถสร้าง% ofTotal ให้เป็นการดำเนินการแบบ one-pass ที่
มหัศจรรย์ได้อย่างไร

@jcolebrand ข้อมูลถูกอ่านจากบล็อกฐานข้อมูลเพียงครั้งเดียว มันอาจจะทำการผ่านหลาย ๆ ครั้งในผลลัพธ์ของหน่วยความจำ แต่โดยทั่วไปจะเร็วกว่าการอ่านบล็อกฐานข้อมูลสองครั้ง มีการแลกเปลี่ยนในหน่วยความจำและ CPU ระหว่างตัวเลือกเหล่านี้ดังนั้นตัวเลือกอาจไม่ชัดเจนเสมอไป แต่ในกรณีนี้ฉันคิดว่ามันเป็น
Leigh Riffel

1
@Leigh ~~ ใช่การพิจารณาต่อไปจะทำให้ฉันเชื่อว่านั่นคือทั้งหมดที่มันสามารถทำได้เพียงแค่กล่องดำกระเพื่อมเพิ่มประสิทธิภาพ อย่างไรก็ตามทางออกที่ดีในคำตอบของคุณ ขอบคุณ: D
jcolebrand

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.