선택 슈퍼 세트 만


10

아래 명령으로 만들 수있는 두 개의 테이블 (클러스터되지 않은 인덱스와 함께)이 있습니다.

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 GroupKeyRecordKeys다른 것과 정확히 같은 것이 들어 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에 다른 GroupKey와 동일한 정확한 RecordKey가 포함 된 경우 해당 GroupKey 중 하나만 잡습니다 (어떤 것이 중요하지는 않습니다).

일치하는 항목이있을 때 가장 낮은 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'세트에 대해 의 UNION을 계산하여이를 달성합니다 . UNION이 'g1'세트보다 큰 경우 'g1'세트 RecordKey에 해당하는 요소 RecordKey가 없는 'g2'세트에 하나 이상 있어야 하므로 'g2'세트는 서브 세트가 아니므로 고려해서는 안됩니다. 이 행.

WHERE 절에는 필터링을 위해 고려해야 할 두 가지 경우가 있습니다. 두 경우 모두 'g1'세트는 모든 'g1' RecordKey이 'g3'세트에도 있는 경우에만 필터링됩니다 . 이 검사는 SELECT 절에 따라 통합을 다시 계산하여 수행됩니다.

두 가지 경우는 다음과 같습니다. ① '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


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.