我正在加入几张表来显示结果
throwError
但是c.ZCOORD的数据类型是INT而d.CODE的数据是NVARCHAR。 我有什么方法可以加入这两个领域吗?
答案 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 JOIN
到ORDERS
。您有一个WHERE
条款AND b.[TYPE] = 'RT-B'
。这会隐式将您的LEFT JOIN
变为INNER JOIN
。这可能对性能不利。
此外,c
和d
(它们又是什么表?)在ON
子句之后永远不会再次引用。它们不在WHERE
或SELECT
中;那他们为什么在那里?他们似乎没有在查询中添加任何内容。
现在,在你的问题上,CODE
是nvarchar
而ZCOORD
是int
。如果您按原样离开,那么根据Data Type Precedence,CODE
将因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引擎很可能会将最复杂的类型转换为更简单的类型,在这种情况下,它将执行从NVARCHAR
到INT
的隐式转换,如比较整数比nvarchars快。
答案 3 :(得分:1)
您可以尝试将d.Code强制转换为int数据类型。 使用
左连接[测试]。[CODELKUP] d on c.ZCOORD = cast(d.CODE as int)