【问题标题】:Find part of string matches with other string SQL查找与其他字符串 SQL 匹配的部分字符串
【发布时间】:2016-06-22 16:46:28
【问题描述】:

我在变量 @var1 = '3,5,6,8' 中分配了一个值。我有一个表,其中包含一些以逗号分隔的随机数组合的列。 PFB样品表

我需要表中除 ID 3 之外的所有值,因为它的组合 '3,9,8' 中有 9。

我希望得到如下答复。

预期输出应仅包含 ID 1,2 和 4。

原因是,@var1 中存在的任何/所有值都应该出现在 Nos 中,并且它不应该有 @var1 中不存在的 no。 Id 3 是后一种情况的示例,它包含不属于@var1 的 9。

我的输出应该有 ID 1,2 和 4 而不是 3。

您能提出一些想法吗?

【问题讨论】:

  • 您应该将这 4 个值作为不同的参数传递。如果你不这样做,那么你将需要在运行 NOT LIKE 之前拆分这些数据
  • PL.有点清楚你需要什么!在第一行,@Var1 有 3、5、6 和 8。但在最后一行你说它在 @Var1 中有 9!
  • 帮自己一个大忙,尽快规范您的数据库。逗号分隔的字符串不是有效的数据类型!
  • @Zohar Peled:谢谢。这不是存储在数据库中的实际表,而是为比较目的而创建的临时表,其中逗号分隔的数据是从表中获取的实际数据的填充。
  • 好。那么改变会更容易。

标签: sql-server-2008


【解决方案1】:

您可以转换为 xml 并使用 xquery:

DECLARE @var1 VARCHAR(100) = '37,39,41,43' 
DECLARE @table TABLE(Id INT, Nos VARCHAR(max)) 
INSERT INTO @table VALUES(1,'37,35,46'),(2,'37,38'),(3,'39,40'),(4,'37,38,39,40,41,42,43,44,45,46') 

SELECT * FROM @table WHERE cast('<n>' + replace(@var1,',','</n><n>') + '</n>' AS XML).exist('//n/.[not(contains(sql:column("nos"),.))]') = 0 
UNION
SELECT * FROM @table WHERE cast('<n>' + replace(Nos,',','</n><n>') + '</n>' AS XML).exist('//n/.[not(contains(sql:variable("@var1"),.))]') = 0 

【讨论】:

  • 谢谢。但没有按预期工作。我试过以下方法:DECLARE @var1 VARCHAR(100) = '37,39,41,43' DECLARE @table TABLE(Id INT, Nos VARCHAR(max)) INSERT INTO @table VALUES(1,'37,35,46'),(2,'37,38'),(3,'39,40'),(4,'37,38,39,40,41,42,43,44,45,46') SELECT * FROM @table WHERE cast('&lt;n&gt;' + replace(Nos,',','&lt;/n&gt;&lt;n&gt;') + '&lt;/n&gt;' AS XML).exist('//n/.[not(contains(sql:variable("@var1"),.))]') = 0
  • 当我运行它时,它没有返回我期望的行,因为在每个行中至少有一个不在列表中的数字;这不是你需要的吗?您希望从这个样本中得到什么输出?
  • 我期望 (4,'37,38,39,40,41,42,43,44,45,46' ) 因为 @ 的所有值 (37, 39, 41, 43) var1 出现在第 4 条记录中。
  • 但这与您的原始问题不一致,其中 var1= '3,5,6,8' 并且没有记录在“nos”列中存在这 4 个值,但是您期望三行返回是因为它们的所有 'nos' 值都在 var1 中。您能否澄清一下您希望以哪种方式进行子集测试:var1 作为“nos”的子集或“nos”作为 var1 的子集?
  • 我已经更新了我的问题。请查看并提出您的宝贵建议。
【解决方案2】:

这还可以进一步减少,但思路如下,

创建一个SplitString函数,

CREATE FUNCTION SplitString
(    
      @Input NVARCHAR(MAX),
      @Character CHAR(1)
)
RETURNS @Output TABLE (
      Item NVARCHAR(1000)
)
AS
BEGIN
      DECLARE @StartIndex INT, @EndIndex INT

      SET @StartIndex = 1
      IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
      BEGIN
            SET @Input = @Input + @Character
      END

      WHILE CHARINDEX(@Character, @Input) > 0
      BEGIN
            SET @EndIndex = CHARINDEX(@Character, @Input)

            INSERT INTO @Output(Item)
            SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)

            SET @Input = rtrim(ltrim(SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))))
      END

      RETURN
END
GO

使用以下一系列查询并对其进行自定义,

DECLARE @t TABLE (ID INT, Nos VARCHAR(8000))
INSERT @t
VALUES (1,
        '5, 3'), (2,
                  '3, 6, 8'), (3,
                               '3, 9, 8'),(4,
                                           '8') IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
DROP TABLE #Temp
SELECT * INTO #Temp
FROM
  (SELECT ID,
          LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS Nos
   FROM
     (SELECT ID,
             CAST('<XMLRoot><RowData>' + REPLACE(Nos,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
      FROM @t)t CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)) P
SELECT '3, 5, 6, 8'
SELECT '(1==> 5, 3), (2==> 3, 6, 8), (3 ==> 3, 9, 8),(4 ==> 8)'
SELECT *
FROM #Temp
SELECT Item
FROM dbo.SplitString('3, 5, 6, 8', ',')
SELECT '-- Group By '
SELECT Id,
       Count(Nos) C
FROM #Temp
GROUP BY Id
SELECT Id,
       Count(Nos) C
FROM
  (SELECT Item
   FROM dbo.SplitString('3, 5, 6, 8', ',')) X
JOIN
  (SELECT Id,
          Nos
   FROM #Temp) Y ON X.Item = Y.Nos
GROUP BY Id
SELECT '-- Final check'
SELECT T.*
FROM
  (SELECT Id,
          Count(Nos) C
   FROM #Temp
   GROUP BY Id) P
JOIN
  (SELECT Id,
          Count(Nos) C
   FROM
     (SELECT Item
      FROM dbo.SplitString('3, 5, 6, 8', ',')) X
   JOIN
     (SELECT Id,
             Nos
      FROM #Temp) Y ON X.Item = Y.Nos
   GROUP BY Id) Q ON P.Id = Q.Id
AND P.C = Q.C
JOIN #Temp T ON T.Id = P.Id

【讨论】:

    猜你喜欢
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-08
    • 2016-04-28
    • 1970-01-01
    • 2015-12-31
    相关资源
    最近更新 更多