0

我有 2 个结构相同的表。

字段 1 INT
FIELD 2 VARCHAR(32) -- 是一个 MD5 哈希

查询必须从表 1 和表 2 中具有字段 2 值的精确组合的记录中获取匹配的字段 1 对。

这些表非常大(两者之间有 100 万条记录),但被推导出为一个 ID 和一个哈希。

示例数据:

表 1

1个
1乙
2个
2 天
2 E
3G
3小时
4 E
4 天
4℃
5 E
5 天

表 2

8个
8乙
9 E
9天
9℃
10楼
11克
11小时
12 乙
12 天
13个
13乙
14 E
14个
查询的结果应该是
8 1
9 4
11 3
13 1

我尝试使用相关子查询和我在此处阅读的 FOR XML PATH 字符串技巧来创建 FIELD 2 的串联字符串,但这非常慢。

4

2 回答 2

1

您也可以尝试以下查询 -

SELECT t_2.Field_1, t_1.Field_1                          --1
  FROM table_1 t_1, table_2 t_2                          --2
 WHERE t_1.Field_2 = t_2.Field_2                         --3
 GROUP BY t_1.Field_1, t_2.Field_1                       --4
HAVING COUNT(*) = (SELECT COUNT(*)                       --5
                     FROM Table_1 t_1_1                  --6
                    WHERE t_1_1.Field_1 = t_1.Field_1)   --7
   AND COUNT(*) = (SELECT COUNT(*)                       --8
                     FROM Table_2 t_2_1                  --9
                    WHERE t_2_1.Field_1 =t_2.Field_1)    --10

编辑

首先,请求的结果集是两个表中的 Field1 的组合,其中各自的 Field2 完全相同。

因此,您可以使用我在上面发布的一种方法。

此处查询将根据 field2 值(从第 1 行到第 3 行)从两个表中获取数据,然后它将根据 table1 中的 field1 和 table2 中的 field1 对数据进行分组(第 4 行)

直到这一步,您将获得来自 table1 的 field1 和来自 table2 的 field2 的结果,其中存在(至少一个)匹配基于表中的 field2 的相应 field1 值。

在此之后,您只需要过滤正确的结果(对于相应的 field1 列值的 field2 值完全相同)。这样您就可以对行数做出条件。

在这里,我的假设是您在任一表中都没有 field1 和 field2 组合的多个值

意味着以下行将不存在 -

1 乙 1 乙

在任何表中。

如果是这样,为 table1 和 table2 获得的相同 field2 值的行数应该与 table1 中为 field1 存在的行匹配,并且相同的行应该只存在于 table2 中的 field2 值。

对于这个条件查询有条件count(*)inhaving子句(从第 5 行到第 10 行)。

于 2013-06-09T12:56:44.303 回答
0

让我试着解释一下这个版本的查询:

select t1.field1 as t1field1, t2.field1 as t2field1
from (select t1.*,
             count(*) over (partition by field1) as NumField2
      from table1 t1
     ) t1 full outer join
     (select t2.*,
             count(*) over (partition by field1) as NumField2
      from table2 t2
     ) t2
     on t1.field2 = t2.field2
where t1.NumField2 = t2.NumField2
group by t1.Field1, t2.Field1
having count(t1.field2) = max(t1.NumField2) and
       count(t2.field2) = max(t2.NumField2)

(在SQLFiddle上)。

这个想法是比较每对field1值的以下计数。

  1. 每个值的数量field2
  2. field2他们共享的值的数量。

所有这些都必须相等。

每个子查询计算field2每个field1值的值的数量。对于数据的第一行,这会产生:

1    A    2
1    B    2
2    A    3
2    D    3
2    E    3
. . .

对于第二张桌子

8    A    2
8    B    2
9    E    3
9    D    3
9    C    3

接下来,应用 ,要求计数和值full outer join都匹配。field2这会使数据相乘,产生如下行:

1    A    2    8    A    2
1    B    2    8    B    2
2    A    3    NULL NULL NULL
2    D    3    9    D    3
2    E    3    9    E    3
NULL NULL NULL 9    C    3

对于所有可能的组合,依此类推。请注意,NULL出现 s 是由于full outer join.

请注意,当您有匹配的一对(例如 1 和 8)时,没有包含NULL值的行。当您有一对具有相同计数但它们不匹配时,那么您就有了NULL值。当您有一对不同计数时,它们会被where子句过滤掉。

过滤聚合步骤应用这些规则来获得满足第一个条件但不满足第二个条件的对。

having本质上删除了任何具有NULL值的对。当您count()使用一列时,NULL不包括值。在这种情况下,count()列上的 小于预期值的数量 ( NumField2)。

于 2013-06-09T19:53:17.280 回答