仅选择超集


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 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大约有7500万行,RecordTable大约有115M行;但是,在连接和WHERE谓词之后,给定的一天大约有2万行。

如果这个问题无关紧要,我深表歉意,但是出于某种原因,我真的很努力。

Answers:


7

我希望输出如下:

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

使用相关子查询是获得所需输出的一种方法。

  • 在一个GroupKey包含与另一个GroupKey完全相同的RecordKeys的情况下,则仅抓住其中一个GroupKey(与哪一个无关)。

当匹配时,我以最低的GroupKey返回Group,但这是任意的,因为您说的没关系。

测试数据:

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'集合,则RecordKey'g2'集合中必须至少有一个没有对应RecordKey的'g1'集合,因此'g2'集合不是子集,因此不应考虑此行。

在WHERE子句中,有两种情况需要考虑进行过滤。在这两种情况下,仅当所有“ g1” RecordKey也都存在于“ g3”集中时才过滤“ g1 ”集合。并且通过再次计算联合(根据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 在这里


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.