Sql 计算差异

Sql 计算差异,sql,sql-server,Sql,Sql Server,我在SQLServerManagementStudio工作 我有一个这样的表:有多个组(D934,D987,…)。在这些组中有多个称为“变体”的子组(A、B、C等)。在这些变体中有多个标识。对于每个标识,都有一个可变的位置编号(标识11436176的位置为10,20和40,标识11436180的位置为10,30和40)。对于每个位置,都有一个对应的值 Group | Variant | Ident | Position | Value -------+--------

我在SQLServerManagementStudio工作

我有一个这样的表:有多个组(D934,D987,…)。在这些组中有多个称为“变体”的子组(A、B、C等)。在这些变体中有多个标识。对于每个标识,都有一个可变的位置编号(标识11436176的位置为10,20和40,标识11436180的位置为10,30和40)。对于每个位置,都有一个对应的值

Group  |  Variant   |  Ident      |  Position  |   Value
-------+------------+-------------+------------+------------
D934   |     A      |  11436176   |   10       |   12548798
D934   |     A      |  11436176   |   20       |   89846465
D934   |     A      |  11436176   |   40       |   98764544
D934   |     A      |  11436180   |   10       |   12548798
D934   |     A      |  11436180   |   30       |   89846487
D934   |     A      |  11436180   |   40       |   98764999
D934   |     B      |  ...        |   ...      |   ...
D934   |     ...    |  ...        |   ...      |   ...
D987   |     A      |  ...        |   ...      |   ...
D987   |     B      |  ...        |   ...      |   ...
D987   |     ...    |  ...        |   ...      |   ...
...    |     ...    |  ...        |   ...      |   ...
我的目标是创建一个查询来比较同一组和变量中的每个ident,并创建一个新的计算列来计算ident之间的差异

当比较两个标识时,我比较每个位置。如果对于同一位置,它们的值不同,则为+1差。如果一个标识存在一个位置,但另一个标识没有,则为+1差异。以下是结果表:

Group  |  Variant   |  Ident 1    |  Ident 2   | Differences
-------+------------+-------------+------------+------------
D934   |     A      |  11436176   |   11436176 |   0
D934   |     A      |  11436176   |   11436180 |   3
说明: 我正在比较标识11436176和11436180。它们都有位置10,该位置的值相同。然后,标识11436176有位置20,但标识11436180没有,所以这是一个区别。然后,标识11436180具有位置30,但标识11436176不具有位置30,因此这是1个差异。然后它们都有位置40,但值不同,所以这是1个不同。总共有3个差异

我认为一个好的开始是在表本身上进行连接,以获得如下内容:

Group  |  Variant  |  Ident 1 |  Ident 2 | Position 1 |  Position 2 | Value 1  | Value 2  | Differences  
-------+-----------+----------+----------+------------+-------------+----------+----------+------------
D934   |     A     | 11436176 | 11436176 |     10     |     10      | 12548798 | 12548798 |     0
D934   |     A     | 11436176 | 11436176 |     20     |     20      | 89846465 | 89846465 |     0
D934   |     A     | 11436176 | 11436176 |     40     |     40      | 98764544 | 98764544 |     0
D934   |     A     | 11436176 | 11436180 |     10     |     10      | 12548798 | 12548798 |     0
D934   |     A     | 11436176 | 11436180 |     20     |     NULL    | 89846465 | NULL     |     1
D934   |     A     | 11436176 | 11436180 |     NULL   |     30      | NULL     | 89846487 |     1
D934   |     A     | 11436176 | 11436180 |     40     |     40      | 98764544 | 98764999 |     1
Group  |  Variant   |  Ident 1    |  Ident 2    |   Differences
-------+------------+-------------+-------------+---------------
D934   |     A      |  11436176   |   11436176  |   0
D934   |     A      |  11436176   |   11436180  |   3
然后进行分组,将差异相加,得到如下结果:

Group  |  Variant  |  Ident 1 |  Ident 2 | Position 1 |  Position 2 | Value 1  | Value 2  | Differences  
-------+-----------+----------+----------+------------+-------------+----------+----------+------------
D934   |     A     | 11436176 | 11436176 |     10     |     10      | 12548798 | 12548798 |     0
D934   |     A     | 11436176 | 11436176 |     20     |     20      | 89846465 | 89846465 |     0
D934   |     A     | 11436176 | 11436176 |     40     |     40      | 98764544 | 98764544 |     0
D934   |     A     | 11436176 | 11436180 |     10     |     10      | 12548798 | 12548798 |     0
D934   |     A     | 11436176 | 11436180 |     20     |     NULL    | 89846465 | NULL     |     1
D934   |     A     | 11436176 | 11436180 |     NULL   |     30      | NULL     | 89846487 |     1
D934   |     A     | 11436176 | 11436180 |     40     |     40      | 98764544 | 98764999 |     1
Group  |  Variant   |  Ident 1    |  Ident 2    |   Differences
-------+------------+-------------+-------------+---------------
D934   |     A      |  11436176   |   11436176  |   0
D934   |     A      |  11436176   |   11436180  |   3

非常感谢,我正在努力解决这个问题

我扩展了您的示例数据,因为如果示例数据中没有
变量
标识
的所有变体,很容易得到错误的查询

本质上,我们需要一个由
(组、变量、标识)
组成的复合键

样本数据

DECLARE @T TABLE(Gr varchar(50), Variant varchar(50), Ident varchar(50), Position varchar(50), Val varchar(50));
INSERT INTO @T VALUES
('D934', 'A', '11436176', '10', '12548798'),
('D934', 'A', '11436176', '20', '89846465'),
('D934', 'A', '11436176', '40', '98764544'),
('D934', 'A', '11436180', '10', '12548798'),
('D934', 'A', '11436180', '30', '89846487'),
('D934', 'A', '11436180', '40', '98764999'),

('D934', 'A', '21436176', '10', '12548798'),
('D934', 'A', '21436176', '20', '89846465'),
('D934', 'A', '21436176', '40', '98764544'),
('D934', 'A', '21436180', '10', '12548798'),
('D934', 'A', '21436180', '30', '89846487'),
('D934', 'A', '21436180', '40', '98764999'),

('D934', 'B', '11436176', '10', '12548798'),
('D934', 'B', '11436176', '20', '89846465'),
('D934', 'B', '11436176', '40', '98764544'),
('D934', 'B', '11436180', '10', '12548798'),
('D934', 'B', '11436180', '30', '89846487'),
('D934', 'B', '11436180', '40', '98764999'),

('D934', 'B', '21436176', '10', '12548798'),
('D934', 'B', '21436176', '20', '89846465'),
('D934', 'B', '21436176', '40', '98764544'),
('D934', 'B', '21436180', '10', '12548798'),
('D934', 'B', '21436180', '30', '89846487'),
('D934', 'B', '21436180', '40', '98764999');
查询

这个问题相当直截了当。有可能存在更有效的变体

WITH
CTE_Idents
AS
(
    SELECT DISTINCT
        Gr, Variant, Ident
    FROM @T
)
,CTE_Join
AS
(
    SELECT
        T1.Gr
        ,T1.Variant
        ,T1.Ident AS Ident1
        ,T2.Ident AS Ident2
    FROM
        CTE_Idents AS T1
        INNER JOIN CTE_Idents AS T2
            ON  T1.Gr = T2.Gr
            AND T1.Variant = T2.Variant
            AND T1.Ident < T2.Ident
)
,CTE_FullJoin
AS
(
SELECT
    CTE_Join.Gr
    ,CTE_Join.Variant
    ,CTE_Join.Ident1
    ,CTE_Join.Ident2
    ,Position1
    ,Position2
    ,Val1
    ,Val2
    ,Diff
FROM
    CTE_Join
    CROSS APPLY
    (
        SELECT *
            ,CASE WHEN Val1 = Val2 THEN 0 ELSE 1 END AS Diff
        FROM
            (
                SELECT
                    T1.Position AS Position1
                    ,T1.Val AS Val1
                FROM @T AS T1
                WHERE
                    T1.Gr = CTE_Join.Gr
                    AND T1.Variant = CTE_Join.Variant
                    AND T1.Ident = CTE_Join.Ident1
            ) AS V1
            FULL JOIN
            (
                SELECT
                    T2.Position AS Position2
                    ,T2.Val AS Val2
                FROM @T AS T2
                WHERE
                    T2.Gr = CTE_Join.Gr
                    AND T2.Variant = CTE_Join.Variant
                    AND T2.Ident = CTE_Join.Ident2
            ) AS V2
            ON V1.Position1 = V2.Position2
    ) AS A
)
SELECT
    Gr
    ,Variant
    ,Ident1
    ,Ident2
    ,SUM(Diff) AS TotalDiff
FROM
    CTE_FullJoin
GROUP BY
    Gr
    ,Variant
    ,Ident1
    ,Ident2
ORDER BY
    Gr
    ,Variant
    ,Ident1
    ,Ident2
;
使用您提供的示例数据

INSERT INTO @T VALUES
('D934', 'A', '11436176', '10', '12548798'),
('D934', 'A', '11436176', '20', '89846465'),
('D934', 'A', '11436176', '40', '98764544'),
('D934', 'A', '11436180', '10', '12548798'),
('D934', 'A', '11436180', '30', '89846487'),
('D934', 'A', '11436180', '40', '98764999');
结果是

| Gr   | Variant | Ident1   | Ident2   | TotalDiff |
|------|---------|----------|----------|-----------|
| D934 | A       | 11436176 | 11436180 | 3         |
工作原理 我建议逐个cte运行查询cte并检查中间结果,以了解其工作原理

我首先在
CTE_Idents
中列出一个键列表。这里的一个键是
(组、变量、标识)的唯一组合

CTE_标识

| Gr   | Variant | Ident    |
|------|---------|----------|
| D934 | A       | 11436176 |
| D934 | A       | 11436180 |
| D934 | A       | 21436176 |
| D934 | A       | 21436180 |
| D934 | B       | 11436176 |
| D934 | B       | 11436180 |
| D934 | B       | 21436176 |
| D934 | B       | 21436180 |
然后我们需要制作所有可能的标识符对。这是在
CTE_Join
中完成的,在这里我们将标识与其自身连接起来。注意过滤器
T1.Ident
-我们不需要两次使用同一对

CTE\U加入

| Gr   | Variant | Ident1   | Ident2   |
|------|---------|----------|----------|
| D934 | A       | 11436176 | 11436180 |
| D934 | A       | 11436176 | 21436176 |
| D934 | A       | 11436180 | 21436176 |
| D934 | A       | 11436176 | 21436180 |
| D934 | A       | 11436180 | 21436180 |
| D934 | A       | 21436176 | 21436180 |
| D934 | B       | 11436176 | 11436180 |
| D934 | B       | 11436176 | 21436176 |
| D934 | B       | 11436180 | 21436176 |
| D934 | B       | 11436176 | 21436180 |
| D934 | B       | 11436180 | 21436180 |
| D934 | B       | 21436176 | 21436180 |
| Gr   | Variant | Ident1   | Ident2   | Position1 | Position2 | Val1     | Val2     | Diff |
|------|---------|----------|----------|-----------|-----------|----------|----------|------|
| D934 | A       | 11436176 | 11436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 11436176 | 11436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | A       | 11436176 | 11436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | A       | 11436176 | 11436180 | 20        | NULL      | 89846465 | NULL     | 1    |
| D934 | A       | 11436176 | 21436176 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 11436176 | 21436176 | 20        | 20        | 89846465 | 89846465 | 0    |
| D934 | A       | 11436176 | 21436176 | 40        | 40        | 98764544 | 98764544 | 0    |
| D934 | A       | 11436180 | 21436176 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 11436180 | 21436176 | NULL      | 20        | NULL     | 89846465 | 1    |
| D934 | A       | 11436180 | 21436176 | 40        | 40        | 98764999 | 98764544 | 1    |
| D934 | A       | 11436180 | 21436176 | 30        | NULL      | 89846487 | NULL     | 1    |
| D934 | A       | 11436176 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 11436176 | 21436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | A       | 11436176 | 21436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | A       | 11436176 | 21436180 | 20        | NULL      | 89846465 | NULL     | 1    |
| D934 | A       | 11436180 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 11436180 | 21436180 | 30        | 30        | 89846487 | 89846487 | 0    |
| D934 | A       | 11436180 | 21436180 | 40        | 40        | 98764999 | 98764999 | 0    |
| D934 | A       | 21436176 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 21436176 | 21436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | A       | 21436176 | 21436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | A       | 21436176 | 21436180 | 20        | NULL      | 89846465 | NULL     | 1    |
| D934 | B       | 11436176 | 11436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 11436176 | 11436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | B       | 11436176 | 11436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | B       | 11436176 | 11436180 | 20        | NULL      | 89846465 | NULL     | 1    |
| D934 | B       | 11436176 | 21436176 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 11436176 | 21436176 | 20        | 20        | 89846465 | 89846465 | 0    |
| D934 | B       | 11436176 | 21436176 | 40        | 40        | 98764544 | 98764544 | 0    |
| D934 | B       | 11436180 | 21436176 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 11436180 | 21436176 | NULL      | 20        | NULL     | 89846465 | 1    |
| D934 | B       | 11436180 | 21436176 | 40        | 40        | 98764999 | 98764544 | 1    |
| D934 | B       | 11436180 | 21436176 | 30        | NULL      | 89846487 | NULL     | 1    |
| D934 | B       | 11436176 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 11436176 | 21436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | B       | 11436176 | 21436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | B       | 11436176 | 21436180 | 20        | NULL      | 89846465 | NULL     | 1    |
| D934 | B       | 11436180 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 11436180 | 21436180 | 30        | 30        | 89846487 | 89846487 | 0    |
| D934 | B       | 11436180 | 21436180 | 40        | 40        | 98764999 | 98764999 | 0    |
| D934 | B       | 21436176 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 21436176 | 21436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | B       | 21436176 | 21436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | B       | 21436176 | 21436180 | 20        | NULL      | 89846465 | NULL     | 1    |
现在,对于具有相同组和变体的每对标识,我们需要查看它们的位置。这是在
CTE\u FullJoin
中完成的。对于每一对
Ident1
Ident2
我们在子查询
V1
中取
Ident1
的所有位置和值,在子查询
V2
中取
Ident2
的所有位置和值

然后我们使用
FULL JOIN
连接
V1
V2
来匹配相同的位置,也包括不匹配的位置。然后,我们比较值并确定它们在
情况下是否相同或不同

CTE_FullJoin

| Gr   | Variant | Ident1   | Ident2   |
|------|---------|----------|----------|
| D934 | A       | 11436176 | 11436180 |
| D934 | A       | 11436176 | 21436176 |
| D934 | A       | 11436180 | 21436176 |
| D934 | A       | 11436176 | 21436180 |
| D934 | A       | 11436180 | 21436180 |
| D934 | A       | 21436176 | 21436180 |
| D934 | B       | 11436176 | 11436180 |
| D934 | B       | 11436176 | 21436176 |
| D934 | B       | 11436180 | 21436176 |
| D934 | B       | 11436176 | 21436180 |
| D934 | B       | 11436180 | 21436180 |
| D934 | B       | 21436176 | 21436180 |
| Gr   | Variant | Ident1   | Ident2   | Position1 | Position2 | Val1     | Val2     | Diff |
|------|---------|----------|----------|-----------|-----------|----------|----------|------|
| D934 | A       | 11436176 | 11436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 11436176 | 11436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | A       | 11436176 | 11436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | A       | 11436176 | 11436180 | 20        | NULL      | 89846465 | NULL     | 1    |
| D934 | A       | 11436176 | 21436176 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 11436176 | 21436176 | 20        | 20        | 89846465 | 89846465 | 0    |
| D934 | A       | 11436176 | 21436176 | 40        | 40        | 98764544 | 98764544 | 0    |
| D934 | A       | 11436180 | 21436176 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 11436180 | 21436176 | NULL      | 20        | NULL     | 89846465 | 1    |
| D934 | A       | 11436180 | 21436176 | 40        | 40        | 98764999 | 98764544 | 1    |
| D934 | A       | 11436180 | 21436176 | 30        | NULL      | 89846487 | NULL     | 1    |
| D934 | A       | 11436176 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 11436176 | 21436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | A       | 11436176 | 21436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | A       | 11436176 | 21436180 | 20        | NULL      | 89846465 | NULL     | 1    |
| D934 | A       | 11436180 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 11436180 | 21436180 | 30        | 30        | 89846487 | 89846487 | 0    |
| D934 | A       | 11436180 | 21436180 | 40        | 40        | 98764999 | 98764999 | 0    |
| D934 | A       | 21436176 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | A       | 21436176 | 21436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | A       | 21436176 | 21436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | A       | 21436176 | 21436180 | 20        | NULL      | 89846465 | NULL     | 1    |
| D934 | B       | 11436176 | 11436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 11436176 | 11436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | B       | 11436176 | 11436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | B       | 11436176 | 11436180 | 20        | NULL      | 89846465 | NULL     | 1    |
| D934 | B       | 11436176 | 21436176 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 11436176 | 21436176 | 20        | 20        | 89846465 | 89846465 | 0    |
| D934 | B       | 11436176 | 21436176 | 40        | 40        | 98764544 | 98764544 | 0    |
| D934 | B       | 11436180 | 21436176 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 11436180 | 21436176 | NULL      | 20        | NULL     | 89846465 | 1    |
| D934 | B       | 11436180 | 21436176 | 40        | 40        | 98764999 | 98764544 | 1    |
| D934 | B       | 11436180 | 21436176 | 30        | NULL      | 89846487 | NULL     | 1    |
| D934 | B       | 11436176 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 11436176 | 21436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | B       | 11436176 | 21436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | B       | 11436176 | 21436180 | 20        | NULL      | 89846465 | NULL     | 1    |
| D934 | B       | 11436180 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 11436180 | 21436180 | 30        | 30        | 89846487 | 89846487 | 0    |
| D934 | B       | 11436180 | 21436180 | 40        | 40        | 98764999 | 98764999 | 0    |
| D934 | B       | 21436176 | 21436180 | 10        | 10        | 12548798 | 12548798 | 0    |
| D934 | B       | 21436176 | 21436180 | NULL      | 30        | NULL     | 89846487 | 1    |
| D934 | B       | 21436176 | 21436180 | 40        | 40        | 98764544 | 98764999 | 1    |
| D934 | B       | 21436176 | 21436180 | 20        | NULL      | 89846465 | NULL     | 1    |
Final
SELECT
计算每对标识的所有差异之和


我试图将原始表与其自身进行
完全联接,但由于复合键以及我们需要比较行的子组,我无法使其正常工作。这就是为什么我显式地创建了标识对,并使用子查询
V1
V2


我强烈建议使用以下索引

(Gr, Variant, Ident) INCLUDE (Position, Val)

对于此查询。

两个以上的示例将非常有用。这看起来很像
行编号()-1
请提供插入表和创建表脚本。您的最佳不工作尝试仍然缺失。您的查询提供了我想要的内容。在我的数据集中,我有大约1000个标识和50000个值,查询结果在1秒内返回,没有任何索引。@JohanB,我很高兴它对您很有效。对于现代硬件来说,您的表相当小,因此任何查询都可以快速工作。如果增长到数以百万计的行,可能需要考虑索引。