PostgreSQL ใช้การนับ () เพื่อกำหนดเปอร์เซ็นต์ (ปัญหาการส่ง)


19

ฉันพยายามเรียกใช้แบบสอบถามต่อไปนี้เพื่อให้% ของแถวในpatientsตารางของฉันที่มีค่าrefinstคอลัมน์ ฉันได้รับผลลัพธ์เป็น 0

select (count (refinst) / (select count(*) from patients) * 100) as "Formula" 
from patients;

ตารางมี 15556 แถวและselect count(refinst) from patientsบอกฉันว่า 1446 ของแถวนั้นมีค่าในrefinstคอลัมน์ การตอบสนองที่ฉันต้องการได้รับจากแบบสอบถามจะเท่ากับ 30.62 ( 1446/15556*100=30.62XXXXXปัดเศษเป็นทศนิยมสองตำแหน่ง)

ฉันค่อนข้างแน่ใจว่ามีบางอย่างเกี่ยวกับประเภทข้อมูลของผลลัพธ์การนับ (จำนวนเต็มที่ฉันสมมติ) หากฉันหารจำนวนเต็มด้วยจำนวนเต็มและผลลัพธ์มีค่าน้อยกว่า 0 จะถูกปัดเศษเป็น 0 ที่ถูกต้องหรือไม่ หากเป็นกรณีนี้มีใครแสดงให้ฉันเห็นวิธีการนับผลลัพธ์เป็นจำนวนที่มีทศนิยม 2 ตำแหน่งเพื่อที่ผลลัพธ์จะถูกปัดเศษเป็นทศนิยม 2 ตำแหน่งเช่นกัน

ฉันแน่ใจว่ามีวิธีที่ดีกว่าในการเขียนรหัสนี้มากกว่าหลายคำสั่งนับ ฉันกำลังมองหาวิธีที่มีประสิทธิภาพโปรเซสเซอร์มากขึ้นในการเขียนแบบสอบถามนี้โดยเฉพาะ


บางทีคำตอบนี้อาจช่วยคุณได้
Jhon Anderson Cardenas Diaz

คำตอบ:


26
SELECT (count(refinst) * 100)::numeric / count(*) AS refinst_percentage
FROM   patients;
  • อย่าได้ใช้ subselect มวลรวมทั้งสองสามารถได้มาจากแบบสอบถามเดียวกัน ถูกกว่า

  • นอกจากนี้นี่ไม่ใช่กรณีสำหรับฟังก์ชันหน้าต่างเนื่องจากคุณต้องการคำนวณผลลัพธ์เดียวและไม่ใช่ผลลัพธ์หนึ่งรายการต่อแถว

  • นักแสดงใด ๆชนิดที่เป็นตัวเลขที่สนับสนุนตัวเลขที่เป็นเศษเช่น@a_horse อธิบายแล้ว
    เนื่องจากคุณต้องการround()เศษส่วนสองหลักฉันแนะนำnumeric(ซึ่งเหมือนกับdecimalใน Postgres)
    แต่มันก็เพียงพอแล้วที่จะใช้ค่าหนึ่งที่เกี่ยวข้องกับการคำนวณโดยเฉพาะอย่างยิ่งค่าแรก Postgres จะตัดสินโดยอัตโนมัติสำหรับประเภทที่ไม่ทำให้ข้อมูลสูญหาย

  • มันเป็นความคิดที่ดีที่จะคูณก่อนที่คุณแบ่ง โดยทั่วไปแล้วจะช่วยลดข้อผิดพลาดในการปัดเศษและมีราคาถูกลง
    ในกรณีนี้การคูณแรก ( count(refinst) * 100) สามารถคำนวณด้วยintegerเลขคณิตราคาถูกและแม่นยำ เท่านั้นจากนั้นเราจะโยนnumericและหารด้วยถัดไปinteger(ซึ่งเราไม่ได้แสดงนอกจากนี้)

ปัดเศษเป็นตัวเลขสองหลัก:

SELECT round((count(refinst) * 100)::numeric / count(*), 2) AS refinst_percentage
FROM   patients;

แน่นอนว่าคุณไม่จำเป็นต้องใช้ฟังก์ชั่นหน้าต่าง แต่มันก็ไม่ได้สร้างความแตกต่าง (นอกเหนือจากการอ่าน)
a_horse_with_no_name

3

คุณต้องโยนแต่ละหมายเลขที่เกี่ยวข้องในการหารให้เป็นประเภทที่รองรับทศนิยม:

select (count(refinst)::decimal / (select count(*) from patients)::decimal) * 100  as "Formula" 
from patients;

คุณอาจต้องการลองใช้ฟังก์ชั่นหน้าต่างแทนแบบสอบถามย่อยสเกลาร์ มันอาจจะเร็วกว่า:

select (count(refinst)::decimal / (count(*) over ())::decimal) * 100 as "Formula" 
from patients;

0

ฉันรู้ว่าเธรดนี้มีอายุสองสามปี แต่: ลองคูณด้วย 100.0 แทนที่จะเป็น 100 นั่นควรแปลงผลลัพธ์เป็นแบบลอยโดยอัตโนมัติแทนที่จะเป็นจำนวนเต็ม

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