bas*_*n22 10 sql-server t-sql sql-server-2014
我有两个可以使用以下命令创建的表(以及一个非聚集索引):
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);
Run Code Online (Sandbox Code Playgroud)
虽然从技术上讲,我的表略有不同,而且我正在加入其他一些表,但这是适合我的情况的代理。
GroupKeys
不是另一个GroupKey
.GroupScore
所有子集(包括其自身)的最大值。GroupKey
包含与RecordKeys
another完全相同的实例中GroupKey(s)
,则只GroupKeys
抓取其中一个(哪个无关紧要)。GroupKey
完全相同的也将具有相同的.RecordKeys
GroupKey(s)
GroupScore
GroupKeys
也可以有相同的分数。下面是一个例子来说明我在问什么:
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);
Run Code Online (Sandbox Code Playgroud)
我希望输出如下:
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
Run Code Online (Sandbox Code Playgroud)
GroupTable
大约有 75M 行,RecordTable
大约有 115M 行;然而,在连接和WHERE
谓词之后,在给定的一天往往有大约 20k 行。
如果这个问题微不足道,我深表歉意,但出于某种原因,我真的很挣扎。
我希望输出如下:
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)
询问:
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
Run Code Online (Sandbox Code Playgroud)
SELECT 中的子查询GroupScore
仅从作为此 ('g1') 组子集的那些组中获得最高值。它通过计算RecordKey
'g1' 集和每个 'g2' 集的's的 UNION 来实现这一点。如果 UNION 大于 'g1' 集,则RecordKey
'g2' 集中必须至少有一个没有对应RecordKey
于 'g1' 集的,因此 'g2' 集不是子集,不应考虑这一行。
在 WHERE 子句中,过滤需要考虑两种情况。在任何一种情况下,只有在所有 'g1'RecordKey
都存在于 'g3' 集中时,才过滤 'g1 ' 集;这个检查是通过再次计算联合来实现的(根据 SELECT 子句)。
这两种情况是: ? 'g1' 集合的RecordKey
s ( g3.RecordCount>g1.RecordCount
; 在这种情况下我们过滤),并且 ? 'g1' 集与 'g3' 集相同(g3.RecordCount=g1.RecordCount
在这种情况下,我们任意选择具有较低 的集GroupKey
)
输出:
/*
|GroupKey|RecordCount|GroupScore|
|-------:|----------:|---------:|
| 1| 3| 9.8|
| 192| 4| 9.8|
*/
Run Code Online (Sandbox Code Playgroud)
dbfiddle在这里
归档时间: |
|
查看次数: |
319 次 |
最近记录: |