我尝试优化此查询以使用联接而不是此子查询,但使用Top 1
时,我有点困惑。
SELECT
s.ItemNumber
s.ImportKey
,(
SELECT top 1 MerchandiseGroupID
FROM MerchandiseGroup mg
WHERE s.StoreDepartment = mg.Name AND c.ClientNumber = s.ClientNumber
) as MerchandiseGroupID
FROM dbo.Source s
INNER JOIN dbo.Client c on s.ClientNumber = c.ClientNumber
INNER JOIN dbo.ClientVendor cv on s.Vendor = cv.ClientVendorName
INNER JOIN dbo.TypeClientWarehouse tw on c.WarehouseCode = tw.WarehouseCode
WHERE s.ImportDate > '2014-05-15 01:00:00.000'
到目前为止我所拥有的:
INNER JOIN
(
SELECT
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY MerchandiseGroupID asc) rnum,
MerchandiseGroupID,
Name
FROM MerchandiseGroup mg
) mhg
ON s.StoreDepartment = mg.Name AND c.ClientNumber = s.ClientNumber
WHERE s.ImportDate > '2014-05-15 01:00:00.000' AND mg.rnum = 1
答案 0 :(得分:1)
我认为使用TOP 1并不是最优于将其转换为连接并使用ROW_NUMBER(),但是如果您想要连接的原因是这样您可以从表中获取其他字段,那么使用APPLY (你的第一个查询没有顶部的顺序,所以我假设它与JOIN尝试中的ROW_NUMBER函数相同):
SELECT
s.ItemNumber,
s.ImportKey,
mg.MerchandiseGroupID,
mg.Name
FROM dbo.Source s
INNER JOIN dbo.Client c on s.ClientNumber = c.ClientNumber
INNER JOIN dbo.ClientVendor cv on s.Vendor = cv.ClientVendorName
INNER JOIN dbo.TypeClientWarehouse tw on c.WarehouseCode = tw.WarehouseCode
OUTER APPLY
(
SELECT top 1 MerchandiseGroupID, Name
FROM MerchandiseGroup mg
WHERE s.StoreDepartment = mg.Name
AND c.ClientNumber = s.ClientNumber
ORDER BY MerchandiseGroupID
) mg
WHERE s.ImportDate > '2014-05-15 01:00:00.000'
如果你只想要前1,这种方法往往比ROW_NUMBER更快,如果你想要特定的记录,它就不那么灵活了,例如第3条记录。
使用日期格式时没有相关性,但是很明显,即使这是ISO标准,它仍然会引发错误:
SET DATEFORMAT DMY;
SELECT CAST('2014-05-15 01:00:00.000' AS DATETIME);
会给你:
Msg 242,Level 16,State 3,Line 2
将varchar数据类型转换为日期时间数据类型会导致超出范围的值。