วิธีนับจำนวนคอลัมน์ที่แตกต่างกันในตารางเดียวกัน


15

ตาราง # 01 Status:

StatusID    Status
-----------------------
 1          Opened
 2          Closed
 3          ReOpened
 4          Pending

ตารางที่ 02 Claims:

ClaimID     CompanyName StatusID
--------------------------------------
1               ABC     1
2               ABC     1
3               ABC     2
4               ABC     4
5               XYZ     1
6               XYZ     1

ผลลัพธ์ที่คาดหวัง:

CompanyName TotalOpenClaims TotalClosedClaims TotalReOpenedClaims TotalPendingClaims
--------------------------------------------------------------------------------
ABC                 2           1                      0               1
XYZ                 2           0                      0               0

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

คำตอบ:


26

มันง่ายที่สุดด้วยSUM()และCASEคำสั่ง:

select CompanyName, 
sum(case when StatusID=1 then 1 else 0 end) as TotalOpenClaims,
sum(case when StatusID=2 then 1 else 0 end) as TotalClosedClaims,
sum(case when StatusID=3 then 1 else 0 end) as TotalReOpenedClaims,
sum(case when StatusID=4 then 1 else 0 end) as TotalPendingClaims
from Claims
group by CompanyName;

16

นี่คือการเปลี่ยนแปลงแบบเดือยทั่วไปและการรวมตามเงื่อนไขตามที่ฟิลแนะนำไว้เป็นวิธีเก่าที่ดีในการนำไปใช้

นอกจากนี้ยังมีไวยากรณ์ที่ทันสมัยมากขึ้นของการบรรลุผลลัพธ์เดียวกันซึ่งใช้ข้อ PIVOT:

SELECT
  CompanyName,
  TotalOpenClaims     = [1],
  TotalClosedClaims   = [2],
  TotalReOpenedClaims = [3],
  TotalPendingClaims  = [4]
FROM
  dbo.Claims
  PIVOT
  (
    COUNT(ClaimID)
    FOR StatusID IN ([1], [2], [3], [4])
  ) AS p
;

ภายในไวยากรณ์ที่ดูง่ายกว่านี้จะเทียบเท่ากับการสืบค้น GROUP BY ของฟิล ยิ่งไปกว่านั้นมันเทียบเท่ากับรูปแบบนี้:

SELECT
  CompanyName,
  TotalOpenClaims     = COUNT(CASE WHEN StatusID = 1 THEN ClaimID END),
  TotalClosedClaims   = COUNT(CASE WHEN StatusID = 2 THEN ClaimID END),
  TotalReOpenedClaims = COUNT(CASE WHEN StatusID = 3 THEN ClaimID END),
  TotalPendingClaims  = COUNT(CASE WHEN StatusID = 4 THEN ClaimID END)
FROM
  dbo.Claims
GROUP BY
  CompanyName
;

ดังนั้นการค้นหาแบบ PIVOT จึงเป็นการสืบค้นแบบกลุ่มโดยนัย

อย่างไรก็ตามแบบสอบถาม PIVOT นั้นมีเล่ห์เหลี่ยมในการจัดการมากกว่าการสืบค้น GROUP BY ที่ชัดเจนด้วยการรวมตามเงื่อนไข เมื่อคุณใช้ PIVOT คุณต้องคำนึงถึงสิ่งนี้เสมอ:

  • คอลัมน์ทั้งหมดของชุดข้อมูลที่มีการหมุน ( Claimsในกรณีนี้) ที่ไม่ได้กล่าวถึงอย่างชัดเจนในข้อเดือยคอลัมน์ GROUP BY

หากClaimsมีเพียงสามคอลัมน์ที่แสดงในตัวอย่างของคุณแบบสอบถาม PIVOT ด้านบนจะทำงานได้ตามที่คาดไว้เพราะเห็นได้ชัดว่าCompanyNameเป็นคอลัมน์เดียวที่ไม่ได้กล่าวถึงอย่างชัดเจนใน PIVOT และท้ายที่สุดจะเป็นเกณฑ์เดียวของกลุ่มตามนัย

อย่างไรก็ตามหากClaimsมีคอลัมน์อื่น (พูดว่าClaimDate) พวกเขาจะถูกนำมาใช้เป็นคอลัมน์ GROUP BY เพิ่มเติมโดยปริยายนั่นคือการค้นหาของคุณจะทำ

GROUP BY CompanyName, ClaimDate, ... /* whatever other columns there are*/`

ผลลัพธ์ส่วนใหญ่จะไม่ใช่สิ่งที่คุณต้องการ

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

SELECT
  CompanyName,
  TotalOpenClaims     = [1],
  TotalClosedClaims   = [2],
  TotalReOpenedClaims = [3],
  TotalPendingClaims  = [4]
FROM
  (SELECT ClaimID, CompanyName, StatusID FROM dbo.Claims) AS derived
  PIVOT
  (
    COUNT(ClaimID)
    FOR StatusID IN ([1], [2], [3], [4])
  ) AS p
;

อย่างไรก็ตามหากClaimsเป็นตารางที่ได้รับมาแล้วไม่จำเป็นต้องเพิ่มการซ้อนในระดับอื่นเพียงตรวจสอบให้แน่ใจว่าในตารางที่ได้รับในปัจจุบันคุณเลือกเฉพาะคอลัมน์ที่จำเป็นในการสร้างเอาต์พุต

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับ PIVOT ได้ในคู่มือ:


1

ประสบการณ์ของฉันเป็นที่ยอมรับกับ MySQL เป็นส่วนใหญ่และฉันไม่ได้ใช้เวลามากกับ SQL Server ฉันจะแปลกใจมากถ้าแบบสอบถามต่อไปนี้ใช้งานไม่ได้:

SELECT 
  CompanyName, 
  status, 
  COUNT(status) AS 'Total Claims' 
FROM Claim AS c 
  JOIN Status AS s ON c.statusId = s.statusId 
GROUP BY 
  CompanyName, 
  status;

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

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