SQL Server Express 2008r2-sp2 外连接基于 3 个公共字段:重复公共字段和 FLOAT->NVARCHAR 转换的问题

问题描述 投票:0回答:1

我有一个关于将同一 SQL Server Express 2008-r2 sp2 数据库中的两个永久表中的数据连接到同一数据库中的第三个永久表的问题。

表中的行需要连接

如果这些表共有的三个字段中的数据匹配

第一个表不包含重复项(并且没有主键),但是可以有多个行其中 3 个公共字段匹配。第二个表确实包含一些重复项,但无法删除它们,因为它们与表的业务逻辑一致;第三个(连接)表的最终用户需要查看三个公共列是否在任何源表中出现多次,如果是,则进一步询问重复项是否是数据质量错误或者它们代表了数据的一部分相同的交易在源数据中使用相同的条目进行预订。

下面我展示了两个源表的简化布局,两个表的公共字段都用 * 标记:


表_1
Table_1

表_2

(来源:bildites.lv

生成的(连接的)表 (

Table_3) 应如下所示:
(来源:bildites.lv

字段

Dup_1

表示公共字段B*、C*和D*的相同组合在表_1中重复的次数。 
Dup_2
 对 Table_2 执行相同的操作。它不考虑这些行是否完全重复,只考虑特定表是否具有公共字段 B*、C* 和 D* 的重复组合。

在复制公共字段的情况下,Table_1 中的哪一行与 Table_2 中的哪一行连接并不重要(不确定也可以) - 例如, [A2-B2-C2-D2-E2-F2-G2] 和 [ A3-B2-C2-D2-E3-F4-G4] 就可以作为表 3 中生成的连接行。最终用户将看到每个源表(Dup_1 和 Dup_2)中公共字段匹配的编号,并采取采取适当的进一步行动。

到目前为止我已采取的步骤: 我尝试看看是否可以将字段 Dup_1 添加到表 1 中。 起初我尝试构造新字段,它是字段 B*、C* 和 D* 的串联:

SELECT Field_A, COALESCE(CAST(Field_B* as NVARCHAR(30)), '') + COALESCE(CAST(Field_C* as NVARCHAR(30)), '') + COALESCE(CAST(Field_D* as NVARCHAR(12)), ''), Field_E, COUNT(COALESCE(CAST(Field_B* as NVARCHAR(30)), '') + COALESCE(CAST(Field_C* as NVARCHAR(30)), '') + COALESCE(CAST(Field_D* as NVARCHAR(12)), '')) FROM Table_1 GROUP BY COALESCE(CAST(Field_B* as NVARCHAR(30)), '') + COALESCE(CAST(Field_C* as NVARCHAR(30)), '') + COALESCE(CAST(Field_D* as NVARCHAR(12)), ''));
这给了我很好的结果(即“B1C1D1”或“B9D9”,其中C9为NULL,以及重复字段组合的数量),

除了Field_C的问题。该字段中的条目都是标准格式的长 ID 号,即 2300034586839938373。它们通过 Openrowset、ACE 和 JET OLEDB 驱动程序(取决于 Excel 文件格式)从 Excel 文件导入到表 1。正确导入它们的唯一方法(不是为了获得科学概念,即 1.08E+05)是将它们作为 FLOAT 变量导入。但是,当我将它们转换为 NVARCHAR 时,它们会被格式化回科学概念,这会产生一个问题,因为 对于表示为 NVARCHAR(科学概念)的同一个 Field_C 条目,各种略有不同的 ID 号(表示为 FLOAT)可以对应*,因此Dup_1在某些情况下会被高估,并且表3中的一些连接条目将丢失。

更新1: 下面我添加 T-SQL 代码来创建上述表表 1 和表 2,其中字段 B、C 和 D 中的数据与我的问题中的实际数据类似:

-- Instead of "JoinTest1" use the name of your testing database USE JoinTest1; IF OBJECT_ID('dbo.Join1', 'U') IS NOT NULL DROP TABLE dbo.Join1; CREATE TABLE dbo.Join1 ( [Field_A] NVARCHAR(2), [Field_B] FLOAT(24), [Field_C] FLOAT(53), [Field_D] DATE, [Field_E] NVARCHAR(2) ); GO EXEC('INSERT INTO dbo.Join1 VALUES (N''A1'', 111.1111, 32822040701 ,''2002-02-01'', N''E1''), (N''A2'', 222.2222, 32822040702 ,''2002-02-02'', N''E2''), (N''A3'', 222.2222, 32822040702 ,''2002-02-02'', N''E3''), (N''A4'', 222.2222, 32822040704 ,''2002-02-02'', N''E4''), (N''A5'', 555.5555, 32822040705 ,''2002-02-05'', N''E5'')') IF OBJECT_ID('dbo.Join2', 'U') IS NOT NULL DROP TABLE dbo.Join2; CREATE TABLE dbo.Join2 ( [Field_F] NVARCHAR(2), [Field_B] FLOAT(24), [Field_C] FLOAT(53), [Field_D] DATE, [Field_G] NVARCHAR(2) ); GO EXEC('INSERT INTO dbo.Join2 VALUES (N''F1'', 111.1111, 32822040701 ,''2002-02-01'', N''G1''), (N''F2'', 222.2222, 32822040702 ,''2002-02-02'', N''G2''), (N''F3'', 222.2222, 32822040702 ,''2002-02-02'', N''G3''), (N''F4'', 222.2222, 32822040702 ,''2002-02-02'', N''G4''), (N''F5'', 222.2222, 32822040704 ,''2002-02-02'', N''G5''), (N''F5'', 222.2222, 32822040704 ,''2002-02-02'', N''G5''), (N''F6'', 666.6666, 32822040706 ,''2002-02-06'', N''G6'')')
出于说明目的,我还发布了创建表 3 的代码 - 连接表 1 和表 2 后我想要的最终结果:

-- Instead of "JoinTest1" use the name of your testing database USE JoinTest1; IF OBJECT_ID('dbo.Join3', 'U') IS NOT NULL DROP TABLE dbo.Join3; CREATE TABLE dbo.Join3 ( [Field_A] NVARCHAR(2), [Field_B] FLOAT(24), [Field_C] FLOAT(53), [Field_D] DATE, [Field_E] NVARCHAR(2), [Field_F] NVARCHAR(2), [Field_G] NVARCHAR(2), [Dup_1] SMALLINT, [Dup_2] SMALLINT ); GO EXEC('INSERT INTO dbo.Join3 VALUES (N''A1'', 111.1111, 32822040701 ,''2002-02-01'', N''E1'', N''F1'', N''G1'', 1, 1), (N''A2'', 222.2222, 32822040702 ,''2002-02-02'', N''E2'', N''F2'', N''G2'', 2, 3), (N''A4'', 222.2222, 32822040704 ,''2002-02-02'', N''E4'', N''F5'', N''G5'', 1, 2), (N''A5'', 555.5555, 32822040705 ,''2002-02-05'', N''E5'', NULL, NULL, 1, NULL), (NULL, 666.6666, 32822040706 ,''2002-02-06'', NULL, N''F6'', N''G6'', NULL, 1)')
最后,我成功地将正确的字符串数据类型列添加到表 1 中(参见下面的代码),因此 FLOAT->NVARCHAR 转换不再是问题。下一步是找到一种方法,如何在表 1 中的这个新列 [3ColStr] 上使用 GROUP BY 以获得 [Dup_1] 列,然后对表 2 执行相同的过程,然后再尝试将它们连接在一起。

-- Instead of "JoinTest1" use the name of your testing database USE JoinTest1; ALTER TABLE dbo.Join1 ADD [3ColStr] AS (COALESCE(CAST([Field_B] as NVARCHAR(12)), '') + COALESCE(CONVERT(NVARCHAR(12),CONVERT(BIGINT, [Field_C])), '') + COALESCE(CONVERT(NVARCHAR(12),[Field_D],20), '')); GO
    
sql sql-server sql-server-2008-r2 duplicates outer-join
1个回答
-1
投票
有人曾经说过,你可以在长数字数据的开头添加一个撇号字符,以便 Excel 忽略它们。

我发现唯一有效的另一件事是隐藏在选项中的设置,该设置会停止根据感知的数据类型自动格式化文档。

http://office.microsoft.com/en-us/excel-help/undo-or-turn-off-automatic-formatting-HA102491299.aspx

不幸的是,后者是特定于用户的。如果您将文件发送给另一个没有关闭该选项的用户,他将看到相同的垃圾数据。

© www.soinside.com 2019 - 2024. All rights reserved.