【问题标题】:SQL involving columns with comma delimited strings and comparisonSQL 涉及以逗号分隔的字符串和比较的列
【发布时间】:2012-06-15 21:40:09
【问题描述】:

我正在更新要求..基本上一个字符串可以有 2 位或 3 位或 4 位小数位,而不是如下所示的两位小数位。

假设我在列名“版本”中有一条以逗号分隔的字符串的记录

假设我们有一条记录 (A),在其“版本”列中包含这些值

Version=10.1.2.4, 10.4.3.4,11.6.0,(该列有逗号分隔的字符串)

我正在传递一个名为 @VersionCheck 的 sql 参数

IF @VersionCheck = 11.6.0 并且 Version 没有像 11.5.6 这样的任何值(注意 11 与 11.6.0 中的 11 匹配)

我要返回记录

所以这里有一些例子都与参数@VersionCheck= 11.6.0进行比较

Version=10.1.2,10.4.3.45 返回这条记录

Version=10.1.2,10.4.3,10.4.4.5,11.6.0 返回此记录(如果我们有匹配的 11.6.0 并且没有以 11 开头的字符串。不等于 11.6.0 (参数传递)我们返回这条记录)

Version= 10.1.2,10.4.3,11.6.0.2 不返回这条记录(要检查,取第一个小数点之前的字符串,在这种情况下是 11,但是 11.6.0.2 和 11.6.0 不是一样,所以不应该匹配)

如何编写 sql 查询以在 where 子句中包含此逻辑? 如果传递的参数是@VersionCheck = 10.6.8,我不希望它匹配如果逗号分隔列中的字符串说 10.5.4 基本上取第一个小数点之前的字符并且它们相等(10 = 10),它的其余值必须相同,否则不应匹配。

这是我在下面的 sql server 2008 语法中的解决方案

注意@SU_Version 是我的参数

SuVersion.fieldValue 是具有逗号分隔字符串值的列,例如 10.1.2、10.3.4 等

WHERE (CASE WHEN '%@SU_Version%' <> '' AND suVersion.fieldValue LIKE LTRIM('@SU_Version')
                THEN suVersion.fieldValue
                ELSE '%'
             END like CASE WHEN '%@SU_Version%' <> '' 
                THEN '%@SU_Version%' 
                ELSE '%'

        END

        AND

        (CASE WHEN LTRIM('@SU_Version') <> '' AND suVersion.fieldValue  LIKE SUBSTRING(LTRIM('@SU_Version'),1, CHARINDEX( '.',LTRIM('@SU_Version'))-1) 
                THEN suVersion.fieldValue
                ELSE'%'
             END not like CASE WHEN LTRIM('@SU_Version')<> ''
                THEN  SUBSTRING(LTRIM('@SU_Version'),1, CHARINDEX( '.',LTRIM('@SU_Version'))-1) + '%'
                ELSE '%'

        END
        AND 

        CASE WHEN LTRIM('@SU_Version') <> '' AND suVersion.fieldValue  LIKE SUBSTRING(LTRIM('@SU_Version'),1, CHARINDEX( '.',LTRIM('@SU_Version'))-1) 
                THEN suVersion.fieldValue
                ELSE'%'
             END not like CASE WHEN LTRIM('@SU_Version')<> ''
                THEN  SUBSTRING(LTRIM('@SU_Version'),1, CHARINDEX( '.',LTRIM('@SU_Version'))-1) + '%'
                ELSE '%'

        END)
      )

【问题讨论】:

  • 为什么列有逗号分隔的字符串?这根本不是一个好的设计。你也能解释一下你的逻辑吗?为什么 VersionCheck = 11.6.0 应该匹配只包含 10.1.2 和 10.4.3 的行?包含 11.6.0 的行匹配,但不包含 11.5.2 的行?这对我来说毫无意义。如果您只对 SQL Server 语法感兴趣,为什么还要标记 MySQL?
  • 如果传递的参数是@VersionCheck = 10.6.8 如果逗号分隔列中的字符串说 10.5.4 我不希望它匹配 基本上取小数点前的字符,如果它们是等于 (10=10),其其余值必须相同,否则不应匹配。

标签: sql sql-server tsql


【解决方案1】:

由于您的设计基本上阻止了任何在版本列上使用索引的尝试,这将为您提供完全匹配的行

...
WHERE ',' + Version + ',' LIKE '%,' + @VersionCheck + ',%'

对于你的时髦要求,试试这个(假设所有版本字符串都包含两个小数位):

DECLARE @v TABLE(Version VARCHAR(MAX));

INSERT @v SELECT ('10.1.2,10.4.3')
UNION ALL SELECT ('10.1.2,10.4.3,11.6.0')
UNION ALL SELECT ('10.1.2,10.4.3,11.5.2');

DECLARE @SU_Version VARCHAR(32);
SET @SU_Version = '11.6.0';

DECLARE 
  @p1 VARCHAR(10),
  @p2 VARCHAR(10);

SELECT
  @p1 = PARSENAME(@SU_Version, 3),
  @p2 = PARSENAME(@SU_Version, 2);

SELECT Version = SUBSTRING(Version, 2, LEN(Version)-2) FROM 
(
  SELECT Version = ',' + Version + ',' FROM @v
) AS v WHERE 
(
  Version LIKE '%,' + @SU_Version + ',%' 
  OR
  Version NOT LIKE '%,' + @p1 + '.%,%'
  AND NOT
  (
    Version LIKE '%,' + @p1 + '.%,%'
    AND
    Version NOT LIKE '%,' + @p1 + '.' + @p2 + '.%,%'
  )
);

【讨论】:

  • 谢谢 Aaron,如果我们有 4 个小数位甚至 5 个小数位怎么办
  • 请发布一个完整要求的问题,以免浪费其他人的时间。
  • “对于你的时髦要求,试试这个(假设所有版本字符串都包含两个小数位)”,不幸的是,情况并非如此,有些可能包含 3 或 4 个小数步伐..很抱歉没有将其包含在要求中
  • 感谢 Aaron,我将尝试操作它以使其满足我以粗体发布的要求
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
  • 2017-04-20
  • 2014-05-15
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多