我正在努力让Tag搜索工作,而且除了LIKE Tag匹配之外它主要工作。
我已将示例代码添加到SQLFiddle进行播放,并将其包含在此处:
表格和数据
CREATE TABLE Attendees
(
Id INT,
Text VARCHAR(500)
);
CREATE TABLE Tags
(
Id INT,
Description VARCHAR(50)
);
CREATE TABLE AttendeeTags
(
AttendeeId INT,
TagId INT,
Value VARCHAR(50)
);
INSERT INTO Attendees VALUES (1, 'Attendee 1');
INSERT INTO Attendees VALUES (2, 'Attendee 2');
INSERT INTO Tags VALUES (1, 'Tag Name 1');
INSERT INTO Tags VALUES (2, 'Tag Name 2');
INSERT INTO AttendeeTags VALUES (1, 1, 'Value 1');
INSERT INTO AttendeeTags VALUES (1, 1, 'Value 2');
INSERT INTO AttendeeTags VALUES (1, 2, 'Value 1');
INSERT INTO AttendeeTags VALUES (1, 2, 'Value 2');
INSERT INTO AttendeeTags VALUES (2, 1, 'Value 1');
查询
DECLARE @MandatoryTagXml XML
SET @MandatoryTagXml = '<tags><tag><description>Tag Name 1</description><value>Value 2</value></tag></tags>'
;WITH MandatoryTags AS
(
SELECT TagValue.value('(./value)[1]', 'nvarchar(100)') AS value,
TagValue.value('(./description)[1]', 'nvarchar(100)') AS [description]
FROM @MandatoryTagXml.nodes('/tags/tag') AS T(TagValue)
)
SELECT DISTINCT A.Id [AttendeeId]
FROM [dbo].[Attendees] A
INNER JOIN [dbo].[AttendeeTags] AT ON AT.AttendeeId = AttendeeId
INNER JOIN [dbo].[Tags] T ON T.Id = AT.TagId AND T.[Description] IN (SELECT [description] FROM MandatoryTags)
WHERE NOT EXISTS (
SELECT T.Id, c.value
FROM MandatoryTags c
JOIN Tags T
ON c.[description] = T.[Description]
-- Add LIKE match to value - This is the problem line
JOIN AttendeeTags AT
ON AT.Value LIKE '%' + C.[Value] + '%'
EXCEPT
SELECT ATT.TagId, ATT.Value
FROM [AttendeeTags] ATT
WHERE ATT.AttendeeId = A.Id
)
我想要的是当Tags.Description与@MandatoryTagXml中的描述完全匹配时获得结果,并且AttendeeTags.Value类似于@MandatoryTagXml中提供的值
如果没有以下行,则按预期工作(即在XML上存在完全匹配时)
JOIN AttendeeTags AT ON AT.Value LIKE '%' + C.[Value] + '%'
但是当我加入它时,我开始得到不正确的结果。例如,设置Value应该返回Attendee.Id,但它不会返回任何结果。
我尝试过各种EXISTS和NOT EXISTS,EXCEPT和INTERSECT等组合,但无法在所有情况下都能使用它。
任何人都可以就如何使其发挥作用提出任何建议吗?
答案 0 :(得分:2)
我认为您的加入比需要的更复杂......
DECLARE @MandatoryTagXml XML
SET @MandatoryTagXml = '
<tags>
<tag><description>Tag Name 1</description><value>Value 1</value></tag>
<tag><description>Tag Name 2</description><value>Value 2</value></tag>
</tags>'
;WITH MandatoryTags AS
(
SELECT TagValue.value('(./value)[1]', 'nvarchar(100)') AS value,
TagValue.value('(./description)[1]', 'nvarchar(100)') AS [description]
FROM @MandatoryTagXml.nodes('/tags/tag') AS T(TagValue)
)
SELECT A.Id [AttendeeId]
FROM [dbo].[Attendees] A
INNER JOIN [dbo].[AttendeeTags] AT
INNER JOIN [dbo].[Tags] T
ON T.Id = AT.TagId
ON AT.AttendeeId = A.Id
INNER JOIN MandatoryTags m
ON T.Description = m.Description
AND AT.Value LIKE ('%' + m.Value + '%')
GROUP BY A.Id
-- Make sure that all of the tags are matched
HAVING COUNT(*) = (SELECT COUNT(*) FROM MandatoryTags)
更新:我已更改SQL以强制对xml中的所有代码进行匹配。
答案 1 :(得分:1)
在子查询中用AT.value替换C.value,这里是链接:
http://sqlfiddle.com/#!6/3d9e9/39
WHERE NOT EXISTS (
SELECT T.Id, AT.Value
FROM MandatoryTags c
JOIN Tags T
ON c.[description] = T.[Description]
-- Add LIKE match to value - This is the problem line
JOIN AttendeeTags AT
ON AT.Value LIKE '%' + C.[Value] + '%'