MSSQL - 如果字段的数据类型不同,如何连接表?

时间:2018-05-16 09:57:56

标签: sql-server

我正在加入几张表来显示结果

throwError

但是c.ZCOORD的数据类型是INT而d.CODE的数据是NVARCHAR。 我有什么方法可以加入这两个领域吗?

4 个答案:

答案 0 :(得分:4)

在查看该查询后,我只需发布一个答案并解释其中的一些问题:

SELECT a.*, b.type 
    FROM [testing].[PICKDETAIL] a
    left join [testing].[ORDERS] b on a.ORDERKEY = b.ORDERKEY
    left join [testing].[LOC] c on A.LOC = c.LOC
    left join [testing].[CODELKUP] d on c.ZCOORD = d.CODE
    WHERE a.STATUS = 0 
    AND b.[TYPE] = 'RT-B'

好的,从哪里开始。首先,我最大的宠物之一,你的走样。 Bad habits to kick : using table aliases like (a, b, c) or (t1, t2, t3)。你拥有它的方式非常令人困惑。 " d"适用于CODELKUP和" c"是LOC?这有什么用呢。

接下来,您的LEFT JOINORDERS。您有一个WHERE条款AND b.[TYPE] = 'RT-B'。这会隐式将您的LEFT JOIN变为INNER JOIN。这可能对性能不利。

此外,cd(它们又是什么表?)在ON子句之后永远不会再次引用。它们不在WHERESELECT中;那他们为什么在那里?他们似乎没有在查询中添加任何内容。

现在,在你的问题上,CODEnvarcharZCOORDint。如果您按原样离开,那么根据Data Type PrecedenceCODE将因int而被隐含转换。如果CODE中的任何值无法转换为int,则会出现问题。例如'1A01'。它还意味着'0101''101''00101'等值将被视为相同的值(101);这可能是也可能不是预期的行为。

无论哪种方式,隐式转换都会使您的查询不具有SARGable,nvarchar的订单结构与int的结构非常不同。例如,使用nvarchar后跟表达式为真:'9' > '8465537632'。是的,这是正确的"数字"九的数值高于"数字#34; 84亿。

这里正确的解决方案是修复您的数据类型,但是,我对您的数据知之甚少,无法提供正确的解决方案。回答;因此,我将采取更安全的选择,将ZCOORD更改为nvarchar,而不是code更改为int

首先,添加新列:

ALTER TABLE testing.LOC ADD COLUMN ZCOORDn nvarchar(100); --I don't know the data size, so you'll need to change this.

接下来,您需要更新新列的值:

UPDATE testing.LOC
SET ZCOORDn = ZCOORD;

现在,我们可以删除旧列并添加新列:

ALTER TABLE testing.LOC DROP COLUMN ZCOORD;
GO
EXEC sp_rename N'testing.LOC.ZCOORDn',N'ZCOORD',N'COLUMN';

现在,您可以编写查询而无需担心隐式转换:

SELECT PD.*, --* is probably a poor choice. Declare your columns
       O.[TYPE] --Be consistance. This was [TYPE] in your WHERE, but it's type here.
FROM [testing].[PICKDETAIL] PD --Changed Alias
     JOIN [testing].[ORDERS] O ON PD.ORDERKEY = O.ORDERKEY --Changed Alias, also now an INNER JOIN
     LEFT JOIN [testing].[LOC] L ON PD.LOC = L.LOC --Changed Alias, is this needed though, it's not in the SELECT, so why is it here?
     LEFT JOIN [testing].[CODELKUP] C on L.ZCOORD = C.CODE --Changed Alias, is this needed though, it's not in the SELECT, so why is it here?
WHERE PD.[STATUS] = 0 
  AND O.[TYPE] = 'RT-B';

请注意我在上面的查询中提出的评论,有很多。

答案 1 :(得分:2)

您可以尝试以下查询

SELECT a.*, b.type 
    FROM [testing].[PICKDETAIL] a
    left join [testing].[ORDERS] b on a.ORDERKEY = b.ORDERKEY
    left join [testing].[LOC] c on A.LOC = c.LOC
    left join [testing].[CODELKUP] d on c.ZCOORD = CAST(d.CODE AS INT)
    WHERE a.STATUS = 0 
    AND b.[TYPE] = 'RT-B'

答案 2 :(得分:1)

如果您确定d.CODE的所有值都将保持整数,那么您可以进行显式转换。如果是这种情况,请考虑将列数据类型更改为int,因为它会减小尺寸并提高性能。

SELECT a.*, b.type 
    FROM [testing].[PICKDETAIL] a
    left join [testing].[ORDERS] b on a.ORDERKEY = b.ORDERKEY
    left join [testing].[LOC] c on A.LOC = c.LOC
    left join [testing].[CODELKUP] d on c.ZCOORD = CONVERT(INT, d.CODE)
    WHERE a.STATUS = 0 
    AND b.[TYPE] = 'RT-B'

如果您不确定或者它可能包含非整数值,那么您的选择将是另一种方式,将c.ZCOORD转换为nvarchar。

SELECT a.*, b.type 
    FROM [testing].[PICKDETAIL] a
    left join [testing].[ORDERS] b on a.ORDERKEY = b.ORDERKEY
    left join [testing].[LOC] c on A.LOC = c.LOC
    left join [testing].[CODELKUP] d on CONVERT(NVARCHAR(20), c.ZCOORD) = d.CODE
    WHERE a.STATUS = 0 
    AND b.[TYPE] = 'RT-B'

这些方法都没有对性能有益,因为您正在将函数(转换数据类型)应用于列,这将使这些列上可能存在的索引的使用无效。

如果保持不变,SQL引擎很可能会将最复杂的类型转换为更简单的类型,在这种情况下,它将执行从NVARCHARINT的隐式转换,如比较整数比nvarchars快。

答案 3 :(得分:1)

您可以尝试将d.Code强制转换为int数据类型。 使用

左连接[测试]。[CODELKUP] d on c.ZCOORD = cast(d.CODE as int)