【问题标题】:How to convert some records ins SQL Server如何在 SQL Server 中转换一些记录
【发布时间】:2023-04-06 04:51:01
【问题描述】:

我有一列的值如下:

## codel ##
1-829549-305-117
1-1196585-305-119
119.305.1983984.1 // this record
1-224594-305-121
1-1999987-305-121
122.306.113416.1 // this record
1-158059-305-122
1-1083888-305-126

将 119.305.1983984.1 转换为 1.1983984.305.119 的代码是:

DECLARE @myvar varchar(20);  
SET @myvar = '119.305.1983984.1';  

SELECT 
    CONCAT(PARSENAME(@myvar, 1), '-',
           PARSENAME(@myvar, 2), '-',
           PARSENAME(@myvar, 3), '-',
           PARSENAME(@myvar, 4)) 

输出应该是:

## codel ##
1-829549-305-117
1-1196585-305-119
1-1983984-305-119 // this record has changed
1-224594-305-121
1-1999987-305-121
1-113416-306-122 // this record has changed
1-158059-305-122

【问题讨论】:

  • 那么实际的问题是什么?
  • 你使用的sql server是什么版本的?
  • 你想对带有破折号的-做同样的事情吗?
  • 你好像在提问的时候忘记了最重要的事情;问一个问题。你的是什么?
  • 猜测,也许,他们想在值以'1'结尾时切换元素的位置,而不是以.开头并更改到-? CONVERT 在这里绝对是错误的词。

标签: sql sql-server tsql


【解决方案1】:

只需将- 替换为.,因为PARSENAME() 仅适用于'.',不适用于'-'

WITH TBL AS
(
  SELECT       '1-829549-305-117' Str
  UNION SELECT '1-1196585-305-119'
  UNION SELECT '119.305.1983984.1' 
  UNION SELECT '1-224594-305-121'
  UNION SELECT '1-1999987-305-121'
  UNION SELECT '122.306.113416.1' 
  UNION SELECT '1-158059-305-122'
  UNION SELECT '1-1083888-305-126'
),
CTE AS
(
  SELECT Str,
         CASE WHEN CHARINDEX('.', Str) > 0 THEN
                   Str
              ELSE REPLACE(Str, '-', '.')
         END Str1
         ,
         CASE WHEN CHARINDEX('.', Str) > 0 THEN '.' ELSE '-' END Sep
  FROM TBL
)
SELECT Str,
       CONCAT(PARSENAME(Str1,1), Sep,
              PARSENAME(Str1,2), Sep,
              PARSENAME(Str1,3), Sep,
              PARSENAME(Str1,4)
              ) Result

FROM CTE;

返回:

+-------------------+-------------------+
|        Str        |      Result       |
+-------------------+-------------------+
| 1-1083888-305-126 | 126-305-1083888-1 |
| 1-1196585-305-119 | 119-305-1196585-1 |
| 1-158059-305-122  | 122-305-158059-1  |
| 119.305.1983984.1 | 1.1983984.305.119 |
| 1-1999987-305-121 | 121-305-1999987-1 |
| 122.306.113416.1  | 1.113416.306.122  |
| 1-224594-305-121  | 121-305-224594-1  |
| 1-829549-305-117  | 117-305-829549-1  |
+-------------------+-------------------+

Live Demo


如果你有 SQL Server 2017,那么你可以使用 CONCAT_WS() 作为

SELECT Str,
       CONCAT_WS(Sep, 
              PARSENAME(Str1,1), 
              PARSENAME(Str1,2), 
              PARSENAME(Str1,3), 
              PARSENAME(Str1,4)
              ) Result

FROM CTE;

如果您希望分隔符始终为'-',则无需Sep,直接'-'即可

【讨论】:

    【解决方案2】:

    您只需要添加此代码

     SELECT [Codel],
    case WHEN  (CHARINDEX('.',[Codel]) > 0) then 
    
        CONCAT(PARSENAME([Codel], 1), '-',
               PARSENAME([Codel], 2), '-',
               PARSENAME([Codel], 3), '-',
               PARSENAME([Codel], 4))  
               else [Codel] end
                true_template
    
      FROM [TestDB].[dbo].[CodelTbl]
    

    【讨论】:

      【解决方案3】:

      以下是如何根据“.”拆分字符串并分别使用这些值:

      create table #temp (rn int identity(1,1), num int)
      
      Declare @products varchar(200) = '119.305.1983984.1'
      Declare @individual varchar(20) = null
      
      WHILE LEN(@products) > 0
      BEGIN
          IF PATINDEX('%.%', @products) > 0
          BEGIN
              SET @individual = SUBSTRING(@products,
                                          0,
                                          PATINDEX('%.%', @products))
              insert into #temp
              SELECT @individual
      
              SET @products = SUBSTRING(@products,
                                        LEN(@individual + '.') + 1,
                                        LEN(@products))
          END
          ELSE
          BEGIN
              SET @individual = @products
              SET @products = NULL
      
              insert into #temp
              SELECT @individual
          END
      END
      select * from #temp
      

      参考:How do I split a string so I can access item x?

      【讨论】:

      • 我真的不推荐WHILE 循环。在 SQL Server 中拆分数据有很多更好的基于集合的解决方案。您链接的问题实际上对使用PARSENAME 的答案有更多的支持; OP正在(好?)使用。
      猜你喜欢
      • 2012-10-22
      • 1970-01-01
      • 2011-06-07
      • 2019-06-22
      • 1970-01-01
      • 2016-01-02
      • 2011-09-20
      • 2015-09-06
      • 1970-01-01
      相关资源
      最近更新 更多