Unpivot ด้วยชื่อคอลัมน์


127

ผมมีตารางที่มีคอลัมน์StudentMarks Name, Maths, Science, Englishข้อมูลก็เหมือน

Name,  Maths, Science, English  
Tilak, 90,    40,      60  
Raj,   30,    20,      10

ฉันต้องการจัดเรียงดังต่อไปนี้:

Name,  Subject,  Marks
Tilak, Maths,    90
Tilak, Science,  40
Tilak, English,  60

ด้วยการไม่ใช้งานฉันสามารถรับชื่อทำเครื่องหมายอย่างถูกต้อง แต่ไม่สามารถรับชื่อคอลัมน์ในตารางต้นทางไปยังSubjectคอลัมน์ในชุดผลลัพธ์ที่ต้องการได้

ฉันจะบรรลุเป้าหมายนี้ได้อย่างไร?

ฉันมาถึงแบบสอบถามต่อไปนี้แล้ว (เพื่อรับชื่อเครื่องหมาย)

select Name, Marks from studentmarks
Unpivot
(
  Marks for details in (Maths, Science, English)

) as UnPvt

1
คุณสามารถโพสต์สิ่งที่คุณทำจนถึงตอนนี้ได้ไหม แบบสอบถาม / ส่งออก
Hart CO

คำตอบ:


204

คำถามของคุณอยู่ใกล้มาก คุณควรจะสามารถใช้สิ่งต่อไปนี้ซึ่งรวมsubjectอยู่ในรายการเลือกสุดท้าย:

select u.name, u.subject, u.marks
from student s
unpivot
(
  marks
  for subject in (Maths, Science, English)
) u;

ดูSQL Fiddle พร้อมการสาธิต


@bluefeet มีวิธีที่คุณไม่จำเป็นต้องระบุชื่อ (คณิตศาสตร์วิทยาศาสตร์อังกฤษ) หรือไม่? ฉันกำลังดำเนินการนี้กับหลาย ๆ ตารางโดยทั้งหมดมีโครงสร้างเดียวกัน แต่มีชื่อคอลัมน์ต่างกัน
LBogaardt

1
@LBogaardt ไม่คุณต้องกำหนดคอลัมน์ที่จะรวมอย่างชัดเจน
jjjjjjjjjjj

@LBogaardt ดูคำตอบของฉันที่นี่คุณสามารถใช้ dynamic sql เพื่อยกเลิกการใช้งานโดยไม่ต้องระบุชื่อคอลัมน์
Taryn

8

คุณอาจลองใช้วิธียกเลิกการ pivoting sql มาตรฐานโดยใช้ลำดับของลอจิกด้วยรหัสต่อไปนี้ .. โค้ดต่อไปนี้มี 3 ขั้นตอน:

  1. สร้างสำเนาหลายชุดสำหรับแต่ละแถวโดยใช้ cross join (สร้างคอลัมน์เรื่องในกรณีนี้ด้วย)
  2. สร้างคอลัมน์ "เครื่องหมาย" และกรอกค่าที่เกี่ยวข้องโดยใช้นิพจน์กรณี (เช่นถ้าหัวเรื่องเป็นวิทยาศาสตร์ให้เลือกค่าจากคอลัมน์วิทยาศาสตร์)
  3. ลบชุดค่าว่างใด ๆ (ถ้ามีอยู่สามารถหลีกเลี่ยงนิพจน์ของตารางได้อย่างสมบูรณ์หากไม่มีค่า null ในตารางฐานอย่างเคร่งครัด)

     select *
     from 
     (
        select name, subject,
        case subject
        when 'Maths' then maths
        when 'Science' then science
        when 'English' then english
        end as Marks
    from studentmarks
    Cross Join (values('Maths'),('Science'),('English')) AS Subjct(Subject)
    )as D
    where marks is not null;

นอกจากนี้ยังใช้งานได้กับ RDBMS ใด ๆ ! เมื่อไม่มีค่าสามารถแทนที่ด้วยแบบสอบถามย่อยที่มี SELECT ... UNION ... SELECT ... สงสัยเกี่ยวกับประสิทธิภาพของ CROSS JOIN แม้ว่า ...
Cristi S.

0

เลือก * จากนักเรียน

UNPIVOT (เครื่องหมายสำหรับวิชาใน (คณิตศาสตร์วิทยาศาสตร์อังกฤษ));


1
นี่เป็นคำตอบเดียวกับคำตอบที่ได้รับการยอมรับและได้รับการโหวตอย่างสูงเมื่อเกือบ 6 ปีก่อน?
ImaginaryHuman072889

0

อีกวิธีหนึ่งในการใช้ cross join คือการระบุชื่อคอลัมน์ภายใน cross join

select name, Subject, Marks 
from studentmarks
Cross Join (
values (Maths,'Maths'),(Science,'Science'),(English,'English')
) un(Marks, Subject)
where marks is not null;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.