Chỉ chọn Supersets


10

Tôi có hai bảng (cùng với một chỉ mục không bao gồm) có thể được tạo bằng các lệnh dưới đây:

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);

Mặc dù về mặt kỹ thuật, các bảng của tôi hơi khác nhau và tôi đang tham gia vào một vài bảng khác, đây là một proxy phù hợp cho tình huống của tôi.

  • Tôi muốn chọn tất cả GroupKeysnhững gì không phải là tập con của người khác GroupKey.
  • Đối với một superset nhất định, tôi muốn lấy tối đa GroupScoretất cả các tập con của nó (bao gồm cả chính nó).
  • Trong trường hợp khi một cái GroupKeychứa chính xác RecordKeysnhư cái khác GroupKey(s), thì chỉ một cái GroupKeysđược lấy (không quan trọng cái nào).
  • Bất kỳ GroupKeycái nào có cùng chính xác RecordKeysnhư cái khác GroupKey(s)cũng sẽ có cùng GroupScore.
  • Không liên quan GroupKeyscó thể có cùng số điểm là tốt.

Sau đây là một ví dụ để minh họa những gì tôi đang hỏi:

              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

Tôi muốn đầu ra là như sau:

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

GroupTablecó khoảng 75M hàng và RecordTablecó khoảng 115M hàng; tuy nhiên, sau khi tham gia và WHEREvị ngữ, có xu hướng có khoảng 20 nghìn hàng vào một ngày nhất định.

Tôi xin lỗi nếu câu hỏi này là tầm thường, nhưng vì một số lý do tôi thực sự vật lộn với nó.

Câu trả lời:


7

Tôi muốn đầu ra là như sau:

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

Sử dụng các truy vấn con tương quan là một cách để có được đầu ra mà bạn muốn.

  • Trong trường hợp khi GroupKey chứa các RecordKey chính xác tương tự như một GroupKey khác, thì chỉ một trong số các GroupKey đó được lấy (không quan trọng là cái nào).

Tôi sẽ trả lại Nhóm với GroupKey thấp nhất khi có trận đấu, nhưng điều đó là tùy tiện như bạn nói nó không thành vấn đề.

dữ liệu kiểm tra:

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

truy vấn:

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

Truy vấn con trong CHỌN đạt mức cao nhất GroupScorechỉ từ các nhóm là tập hợp con của nhóm ('g1') này. Nó đạt được điều này bằng cách đếm UNION của RecordKeybộ 'g1' và mỗi bộ 'g2'. Nếu UNION lớn hơn bộ 'g1', thì phải có ít nhất một RecordKeytrong bộ 'g2' không có bộ tương ứng RecordKeycho bộ 'g1', vì vậy bộ 'g2' không phải là tập hợp con và không nên xem xét cho hàng này.

Trong mệnh đề WHERE, có hai trường hợp cần xem xét để lọc. Trong cả hai trường hợp, bộ 'g1' chỉ được lọc nếu tất cả các 'g1' RecordKeycũng có trong bộ 'g3'; và kiểm tra này đạt được bằng cách đếm lại liên minh (theo mệnh đề SELECT).

Hai trường hợp là: tập 'g1' có ít RecordKeys hơn ( g3.RecordCount>g1.RecordCounttrong trường hợp đó chúng tôi lọc) và tập 'g1' giống hệt với tập 'g3' ( g3.RecordCount=g1.RecordCounttrong trường hợp đó chúng tôi tùy ý chọn tập hợp với thấp hơn GroupKey)

đầu ra:

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

dbfiddle ở đây


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.