เลือก Supersets เท่านั้น


10

ฉันมีสองตาราง (พร้อมกับดัชนี nonclustered) ที่สามารถสร้างด้วยคำสั่งด้านล่าง:

CREATE TABLE GroupTable
(
  GroupKey int NOT NULL PRIMARY KEY, 
  RecordCount int NOT NULL,
  GroupScore float NOT NULL
);

CREATE TABLE RecordTable
(
  RecordKey varchar(10) NOT NULL, 
  GroupKey int NOT NULL,
  PRIMARY KEY(RecordKey, GroupKey)
);

CREATE UNIQUE INDEX ixGroupRecord ON RecordTable(GroupKey, RecordKey);

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

  • ฉันต้องการเลือกทั้งหมดGroupKeysที่ไม่ใช่ชุดย่อยของอีกGroupKeyชุด
  • สำหรับชุดที่ได้รับฉันต้องการคว้าGroupScoreชุดย่อยสูงสุดของมันทั้งหมด (รวมถึงตัวเอง)
  • ในอินสแตนซ์เมื่อ a GroupKeyมีค่าที่แน่นอนเหมือนกันRecordKeysกับอีกค่าGroupKey(s)หนึ่งค่านั้นGroupKeysจะถูกจับเท่านั้น (ไม่สำคัญว่าอันไหน)
  • ใด ๆGroupKeyที่มีเหมือนกันที่แน่นอนRecordKeysอีกก็จะต้องมีเหมือนกันGroupKey(s)GroupScore
  • ไม่เกี่ยวข้องGroupKeysสามารถมีคะแนนเดียวกันเช่นกัน

ต่อไปนี้เป็นตัวอย่างเพื่อแสดงสิ่งที่ฉันขอ:

              GroupTable                          RecordTable

GroupKey    RecordCount   GroupScore         RecordKey    GroupKey
------------------------------------         ---------------------
  1              3            6.2                A          1
  29             2            9.8                A          29
  95             3            6.2                A          95
  192            4            7.1                A          192
                                                 B          1
                                                 B          29
                                                 B          95
                                                 B          192
                                                 C          1
                                                 C          95
                                                 D          192
                                                 E          192

ฉันต้องการให้ผลลัพธ์เป็นดังต่อไปนี้:

GroupKey    RecordCount    GroupScore
-------------------------------------
  1              3             9.8
  192            4             9.8

GroupTableมีแถวประมาณ 75M และRecordTableมีแถวประมาณ 115M อย่างไรก็ตามหลังจากการรวมและการWHEREสรุปมีแนวโน้มที่จะมีประมาณ 20k แถวในวันที่กำหนด

ฉันขอโทษถ้าคำถามนี้เล็กน้อย แต่ด้วยเหตุผลบางอย่างฉันจริงๆดิ้นรนกับมัน

คำตอบ:


7

ฉันต้องการให้ผลลัพธ์เป็นดังต่อไปนี้:

 GroupKey    RecordCount    GroupScore
 -------------------------------------
   1              3             9.8
   192            4             7.1

การใช้เคียวรีย่อยที่สัมพันธ์กันเป็นวิธีหนึ่งในการรับเอาต์พุตที่คุณต้องการ

  • ในอินสแตนซ์เมื่อ GroupKey มี RecordKey ที่แน่นอนเช่นเดียวกับ GroupKey อื่นจากนั้นมี GroupKeys เพียงหนึ่งแห่งเท่านั้นที่ถูกคว้า

ฉันจะคืนกลุ่มด้วย GroupKey ที่ต่ำที่สุดเมื่อมีการแข่งขัน แต่มันเป็นเรื่องแบบสุ่มตามที่คุณบอกว่ามันไม่สำคัญ

ข้อมูลการทดสอบ:

INSERT INTO RecordTable(RecordKey,GroupKey)
VALUES ('A',1)
     , ('A',29)
     , ('A',95)
     , ('A',192)
     , ('B',1)
     , ('B',29)
     , ('B',95)
     , ('B',192)
     , ('C',1)
     , ('C',95)
     , ('D',192)
     , ('E',192);

INSERT INTO GroupTable(GroupKey,RecordCount,GroupScore)
VALUES (1,3,6.2)     -- ABC
     , (29,2,9.8)    -- AB
     , (95,3,6.2)    -- ABC
     , (192,4,7.1);  -- ABDE
GO

แบบสอบถาม:

SELECT GroupKey
     , RecordCount
     , GroupScore = ( SELECT max(GroupScore)
                      FROM GroupTable g2 
                      WHERE ( SELECT count(*)
                              FROM ( SELECT RecordKey
                                     FROM RecordTable
                                     WHERE GroupKey=g1.GroupKey
                                     UNION
                                     SELECT RecordKey
                                     FROM RecordTable
                                     WHERE GroupKey=g2.GroupKey ) z
                            )=g1.RecordCount )
FROM GroupTable g1
WHERE NOT EXISTS ( SELECT *
                   FROM GroupTable g3
                   WHERE ( SELECT count(*)
                           FROM ( SELECT RecordKey
                                  FROM RecordTable 
                                  WHERE GroupKey=g1.GroupKey 
                                  UNION
                                  SELECT RecordKey 
                                  FROM RecordTable 
                                  WHERE GroupKey=g3.GroupKey ) z )=g3.RecordCount
                         AND ( g3.RecordCount>g1.RecordCount 
                               OR ( g3.RecordCount=g1.RecordCount 
                                    AND g3.GroupKey<g1.GroupKey ) ) );
GO

ข้อความค้นหาย่อยใน SELECT ได้รับคะแนนสูงสุดGroupScoreจากกลุ่มที่เป็นชุดย่อยของกลุ่มนี้ ('g1') เท่านั้น ทำได้โดยการนับจำนวนของRecordKey'g1' และ 'g2' แต่ละชุด หากยูเนี่ยนมีขนาดใหญ่กว่าชุด 'g1' จะต้องมีอย่างน้อยหนึ่งชุดRecordKeyในชุด 'g2' โดยไม่ต้องตรงRecordKeyกับชุด 'g1' ดังนั้นชุด 'g2' จึงไม่ใช่ชุดย่อยและไม่ควรนำมาพิจารณา แถวนี้

ในส่วนคำสั่ง WHERE มีสองกรณีที่ต้องพิจารณาสำหรับการกรอง ในกรณีใดกรณีหนึ่งชุด 'g1' จะถูกกรองก็ต่อเมื่อชุด 'g1' RecordKeyทั้งหมดนั้นมีอยู่ในชุด 'g3' ด้วยเช่นกัน และการตรวจสอบนี้ทำได้โดยการนับยูเนี่ยนอีกครั้ง (ตามข้อเลือก)

ทั้งสองกรณีคือ: ①ชุด 'g1' มีRecordKeys น้อยกว่า( g3.RecordCount>g1.RecordCountในกรณีที่เรากรองข้อมูล) และ②ชุด 'g1' นั้นเหมือนกับชุด 'g3' ( g3.RecordCount=g1.RecordCountในกรณีนี้เราเลือกชุดด้วย ต่ำกว่าGroupKey)

เอาท์พุท:

/*
|GroupKey|RecordCount|GroupScore|
|-------:|----------:|---------:|
|       1|          3|       9.8|
|     192|          4|       9.8|
*/

dbfiddle ที่นี่


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