SQL SELECT其中标记值为LIKE

前端之家收集整理的这篇文章主要介绍了SQL SELECT其中标记值为LIKE前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试制作日历服务,在该日历服务中,有事件,并且事件可以使用可搜索的元数据进行标记.

我希望能够搜索所有标记必须存在的记录(强制标记)和/或存在任何标记的位置(可选标记).

标签值与’exact’匹配时,我设法创建了一个可以工作的查询.但我无法弄清楚如何返回标签值为LIKE’%value%’的结果.

这是我目前的实施

表和数据

  1. CREATE TABLE Events
  2. (
  3. Id INT,EventText VARCHAR(500)
  4. );
  5.  
  6. CREATE TABLE EventDates
  7. (
  8. Id INT,EventId INT,StartDate DATETIME,EndDate DATETIME,Archived BIT
  9. );
  10.  
  11. CREATE TABLE Tags
  12. (
  13. Id INT,Description VARCHAR(50)
  14. );
  15.  
  16. CREATE TABLE EventTags
  17. (
  18. EventId INT,TagId INT,Value VARCHAR(50)
  19. );
  20.  
  21. INSERT INTO Events VALUES (1,'Event Name 1');
  22. INSERT INTO Events VALUES (2,'Event Name 2');
  23.  
  24. INSERT INTO EventDates VALUES (1,1,'2013-01-01','2013-01-02',0);
  25. INSERT INTO EventDates VALUES (2,'2013-01-07','2013-01-08',0);
  26. INSERT INTO EventDates VALUES (3,2,'2013-01-03',0);
  27.  
  28. INSERT INTO Tags VALUES (1,'Tag Name 1');
  29. INSERT INTO Tags VALUES (2,'Tag Name 2');
  30.  
  31. INSERT INTO EventTags VALUES (1,'Value 1');
  32. INSERT INTO EventTags VALUES (1,'Value 2');
  33. INSERT INTO EventTags VALUES (1,'Value 2');
  34. INSERT INTO EventTags VALUES (2,'Value 1');

询问

  1. DECLARE @MandatoryTagXml XML
  2. DECLARE @OptionalTagXml XML
  3. DECLARE @StartDate DATETIME
  4. DECLARE @EndDate DATETIME
  5. DECLARE @SearchTypeId SMALLINT
  6.  
  7. SET @StartDate = '2013-01-01'
  8. SET @EndDate = '2013-01-31'
  9. SET @SearchTypeId = 1
  10.  
  11. -- Tags that it must match all of
  12. SET @MandatoryTagXml = '<tags>
  13. <tag>
  14. <description>Tag Name 1</description>
  15. <value>Value 1</value>
  16. </tag>
  17. </tags>'
  18.  
  19. -- Tags that it can match one or more of
  20. SET @OptionalTagXml = '<tags>
  21. <tag>
  22. <description>Tag Name 2</description>
  23. <value>Value 2</value>
  24. </tag>
  25. </tags>'
  26.  
  27. DECLARE @MandatoryIdTable TABLE ([EventId] BIGINT,[EventDateId] BIGINT)
  28. DECLARE @OptionalIdTable TABLE ([EventId] BIGINT,[EventDateId] BIGINT)
  29.  
  30. IF(@MandatoryTagXml IS NOT NULL)
  31. BEGIN
  32. -- Select ids with matching mandatory tags.
  33. ;WITH MandatoryTags AS
  34. (
  35. SELECT TagValue.value('(./value)[1]','nvarchar(100)') AS value,TagValue.value('(./description)[1]','nvarchar(100)') AS [description]
  36. FROM @MandatoryTagXml.nodes('/tags/tag') AS T(TagValue)
  37. )
  38.  
  39. INSERT INTO @MandatoryIdTable
  40. -- Records where ALL tags match EXACTLY
  41. SELECT E.Id [EventId],ED.Id [EventDateId]
  42. FROM [dbo].[Events] E
  43. INNER JOIN [dbo].[EventDates] ED ON ED.EventId = E.Id
  44. WHERE ED.StartDate >= @StartDate
  45. AND ED.EndDate <= @EndDate
  46. AND ED.Archived = 0
  47. AND NOT EXISTS (
  48. SELECT T.Id,c.value
  49. FROM MandatoryTags c JOIN Tags T
  50. ON c.[description] = T.[Description]
  51. EXCEPT
  52. SELECT T.TagId,T.Value
  53. FROM [EventTags] T
  54. WHERE T.EventId = E.Id
  55. )
  56. END
  57. ELSE -- Select All records
  58. BEGIN
  59. INSERT INTO @MandatoryIdTable
  60. -- Records where ALL tags match EXACTLY
  61. SELECT E.Id [EventId],ED.Id [EventDateId]
  62. FROM [dbo].[Events] E
  63. INNER JOIN [dbo].[EventDates] ED ON ED.EventId = E.Id
  64. WHERE ED.StartDate >= @StartDate
  65. AND ED.EndDate <= @EndDate
  66. AND ED.Archived = 0
  67. END
  68.  
  69. ;WITH OptionalTags AS
  70. (
  71. SELECT TagValue.value('(./value)[1]','nvarchar(100)') AS [description]
  72. FROM @OptionalTagXml.nodes('/tags/tag') AS T(TagValue)
  73. )
  74.  
  75. INSERT INTO @OptionalIdTable
  76. -- Records ANY tags match EXACTLY
  77. SELECT E.Id [EventId],ED.Id [EventDateId]
  78. FROM [dbo].[Events] E
  79. INNER JOIN [dbo].[EventDates] ED ON ED.EventId = E.Id
  80. WHERE ED.StartDate >= @StartDate
  81. AND ED.EndDate <= @EndDate
  82. AND ED.Archived = 0
  83. AND EXISTS (
  84. SELECT T.Id,c.value
  85. FROM OptionalTags c JOIN Tags T
  86. ON c.[description] = T.[Description]
  87. INTERSECT
  88. SELECT T.TagId,T.Value
  89. FROM [EventTags] T
  90. WHERE T.EventId = E.Id
  91. )
  92.  
  93. -- Determine if we need to factor in optional tags in result set
  94. IF (@OptionalTagXml IS NOT NULL)
  95. BEGIN
  96. -- Select results that exist in both optional and mandatory tables
  97. SELECT DISTINCT M.*
  98. FROM @MandatoryIdTable M
  99. INNER JOIN @OptionalIdTable O ON O.EventId = M.EventId AND O.EventDateId = M.EventDateId
  100. END
  101. ELSE
  102. BEGIN
  103. -- Select results that exist in mandatory table
  104. SELECT DISTINCT M.*
  105. FROM @MandatoryIdTable M
  106. END

我为它创建了一个SQLFiddle Demo.

我的想法是使用@SearchTypeId在完全匹配搜索和LIKE匹配搜索之间切换.

(注意我不是DBA,所以可能有更好的方法来做到这一点.我愿意接受建议)

任何人都可以提供关于如何在标签值上获得LIKE匹配的建议吗?

非常感谢

解决方法

我认为你使用某种类型的标志/开关来改变匹配类型的想法将起作用.我使用单词而不是ID实现它,但如果您只是根据搜索类型切换连接条件,您应该按预期获得LIKE匹配.

小提琴:http://sqlfiddle.com/#!3/d9fbd/3/0

我首先添加了一个类似于标签1的标签,并将其附加到事件2进行测试.

  1. INSERT INTO Tags VALUES (3,'Different Tag Name 1');
  2. INSERT INTO EventTags VALUES (2,3,'Value 3');

然后我创建了搜索类型标志/开关.

  1. DECLARE @SearchType NVARCHAR(10)
  2. SET @SearchType = 'LIKE' --other type is EXACT

所以现在您可以根据该标志切换EXISTS连接条件.为了我的理解,我将你的NOT EXISTS改为EXISTS.下面是新的连接条件,使用强制标记块作为示例.

  1. -- Select ids with matching mandatory tags.
  2. ;WITH MandatoryTags AS
  3. (
  4. SELECT TagValue.value('(./value)[1]','nvarchar(100)') AS [description]
  5. FROM @MandatoryTagXml.nodes('/tags/tag') AS T(TagValue)
  6. )
  7.  
  8. INSERT INTO @MandatoryIdTable
  9. -- Records where ALL tags match EXACTLY or LIKE
  10. SELECT E.Id [EventId],ED.Id [EventDateId]
  11. FROM [dbo].[Events] E
  12. INNER JOIN [dbo].[EventDates] ED ON ED.EventId = E.Id
  13. WHERE ED.StartDate >= @StartDate
  14. AND ED.EndDate <= @EndDate
  15. AND ED.Archived = 0
  16. AND EXISTS (
  17. -- Just care about tag IDs here,not the values
  18. SELECT T.Id
  19. FROM MandatoryTags c JOIN Tags T
  20. ON (
  21. -- Toggle join type based on flag/switch
  22. (@SearchType = 'EXACT' AND c.[description] = T.[Description])
  23. OR
  24. (@SearchType = 'LIKE' AND T.[Description] LIKE ('%' + c.[description] + '%'))
  25. )
  26. INTERSECT
  27. SELECT T.TagId
  28. FROM [EventTags] T
  29. WHERE T.EventId = E.Id
  30. )

我确信你可以在这个sql中做一些重新分解和优化,但这至少应该让你知道如何在需要时进行LIKE匹配.希望能帮助到你!

猜你在找的MsSQL相关文章