我需要比较两个xml列。我目前有大约1000行数据正在运行,大约需要20分钟。无论如何,我可以改进此查询以更快地运行。
SELECT
MAX(T.CaseName) AS CaseName,
T.PartNumber,
T.NodeName,
T.OldValue,
T.NewValue
FROM (SELECT
C.CaseName,
old.N.value('../../../MaterialName[1]', 'nvarchar(100)') AS PartNumber,
old.N.value('Name[1]', 'nvarchar(4000)') AS NodeName,
old.N.value('Value[1]', 'nvarchar(4000)') AS OldValue,
new.N.value('Value[1]', 'nvarchar(4000)') AS NewValue
FROM Cases c
CROSS APPLY BomDataCase.nodes('/TopBomComponents/TopBomComponents/TopBomComponent/BomMaterials/BomMaterial/BomMaterialAttributes/CustomBomMaterialAttributes/CustomBomMaterialAttribute') AS old (N)
CROSS APPLY BomDataChange.nodes('/TopBomComponents/TopBomComponents/TopBomComponent/BomMaterials/BomMaterial/BomMaterialAttributes/CustomBomMaterialAttributes/CustomBomMaterialAttribute') AS new (N)
INNER JOIN LibraryStatuses ls
ON c.[Status] = ls.StatusId
AND c.LibraryId = ls.LibraryId
WHERE old.N.value('../../../MaterialName[1]', 'nvarchar(100)') = new.N.value('../../../MaterialName[1]', 'nvarchar(100)')
AND old.n.value('Name[1]', 'nvarchar(100)') = new.n.value('Name[1]', 'nvarchar(100)')
AND old.n.value('Value[1]', 'nvarchar(100)') <> new.n.value('Value[1]', 'nvarchar(100)')
AND ls.name = 'Review') AS T
GROUP BY T.PartNumber,
T.NodeName,
T.OldValue,
T.NewValue
每个xml字符串相当大,大约1000到1500行。
这是Cases表结构。
CREATE TABLE [dbo].[Cases](
[CaseId] [int] IDENTITY(1,1) NOT NULL,
[LibraryId] [int] NOT NULL,
[CaseName] [nvarchar](500) NULL,
[ConfigId] [nvarchar](50) NOT NULL,
[CurrentConfigId] [nvarchar](50) NULL,
[PartNumber] [nvarchar](50) NOT NULL,
[Image] [nvarchar](250) NULL,
[Status] [int] NULL,
[Price] [decimal](18, 0) NULL,
[Comments] [nvarchar](500) NULL,
[Error] [nvarchar](max) NULL,
[LastRun] [datetime] NULL,
[LastRunApplication] [nvarchar](100) NULL,
[BomDataCase] [xml] NULL,
[BomDataChange] [xml] NULL,
CONSTRAINT [PK_Cases] PRIMARY KEY CLUSTERED
(
[CaseId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
答案 0 :(得分:1)
这个答案来得太晚了,希望它还值得张贴...
阅读XML应该直接进行。真正沉重且昂贵的是向后导航,正如您使用../../..
执行此操作
最好完成某个级别并从此点继续APPLY
。
如果没有看到实际的XML,这可能不正确,但您应该明白这一点:
SELECT
MAX(T.CaseName) AS CaseName,
T.PartNumber,
T.NodeName,
T.OldValue,
T.NewValue
FROM (SELECT
C.CaseName,
old.mat.N.value('MaterialName[1]', 'nvarchar(100)') AS PartNumber,
old.N.value('Name[1]', 'nvarchar(4000)') AS NodeName,
old.N.value('Value[1]', 'nvarchar(4000)') AS OldValue,
new.N.value('Value[1]', 'nvarchar(4000)') AS NewValue
FROM Cases c
CROSS APPLY BomDataCase.nodes('/TopBomComponents/TopBomComponents/TopBomComponent/BomMaterials/BomMaterial') AS old (mat)
CROSS APPLY old.mat.nodes('BomMaterialAttributes/CustomBomMaterialAttributes/CustomBomMaterialAttribute') AS old (N)
CROSS APPLY BomDataChange.nodes('/TopBomComponents/TopBomComponents/TopBomComponent/BomMaterials/BomMaterial') AS new (mat)
CROSS APPLY new.mat.nodes('BomMaterialAttributes/CustomBomMaterialAttributes/CustomBomMaterialAttribute') AS new (N)
INNER JOIN LibraryStatuses ls
ON c.[Status] = ls.StatusId
AND c.LibraryId = ls.LibraryId
WHERE mat.N.value('MaterialName[1]', 'nvarchar(100)') = mat.N.value('MaterialName[1]', 'nvarchar(100)')
AND old.n.value('Name[1]', 'nvarchar(100)') = new.n.value('Name[1]', 'nvarchar(100)')
AND old.n.value('Value[1]', 'nvarchar(100)') <> new.n.value('Value[1]', 'nvarchar(100)')
AND ls.name = 'Review') AS T
GROUP BY T.PartNumber,
T.NodeName,
T.OldValue,
T.NewValue