【问题标题】:how to separate string into different columns?如何将字符串分成不同的列?
【发布时间】:2012-06-25 07:46:29
【问题描述】:

我有一张表,里面有这样的条目。

    MachineName
-----------------------

    Ab bb zecos
    a zeng
    zeng
    empty

一个表中有 4 行。

如何将这 4 行分开以获得类似的输出。

       M1       M2       M3
-----------------------------------
       Ab       bb      zecos
       a        zeng     NULL
       zeng     NULL     NULL
       NULL     NULL     NULL

【问题讨论】:

  • 这不是偶然的,因此您可以将标签应用于元素,对吗?
  • @BradChristie 没找到你!
  • 因为你不明白这个问题?我在问您是否主要目的是将标签应用于项目(几乎就像博客对帖子所做的那样),现在您正试图将它们检索回来。
  • 创建一个包含 M1、M2、M3 列的临时表,获取机器名称,按空格拆分名称并在新表中插入行

标签: sql sql-server sql-server-2008


【解决方案1】:

有一个名为 ParseName 的函数而不是使用拆分函数,它返回对象的指定部分,该部分拆分由 分隔的字符串。 请通过 ParseName 链接帮助我编写此查询

Declare @Sample Table
(MachineName varchar(max))

Insert into @Sample
values 
('Ab bb zecos'),('a Zeng')


  SELECT 
  Reverse(ParseName(Replace(Reverse(MachineName), ' ', '.'), 1)) As [M1]
 , Reverse(ParseName(Replace(Reverse(MachineName), ' ', '.'), 2)) As [M2]
 , Reverse(ParseName(Replace(Reverse(MachineName), ' ', '.'), 3)) As [M3]

  FROM  (Select MachineName from @Sample
  ) As [x] 

【讨论】:

  • 我记得关于 PARSENAME 不允许超过 4 个项目(因为它用于对象名称,并且 4 个部分是对象标识符的最大长度) - 所以只要你记得,你就可以使用它:)
  • 是的,谢谢你提醒我,但我认为 OP 在他的问题中提到只有 3 列
  • 完美……这也是我想要的……非常感谢 :)
  • 如果拆分段为空白,您可能不会得到所有段的返回结果。为避免这种情况,我执行以下操作(我使用 + 作为它不在列中,但您可以使用任何未使用的字符): Replace(ParseName(Replace(DELADD.CONTACT_VALUE, CHAR(10), '+.+'), 3) ,'+','')
【解决方案2】:

使用 Parsename() 函数

with cte as(
    select 'Aria Karimi' as FullName
    Union
    select 'Joe Karimi' as FullName
    Union
    select 'Bab Karimi' as FullName
)

SELECT PARSENAME(REPLACE(FullName,' ','.'),2) as Name, PARSENAME(REPLACE(FullName,' ','.'),1) as Family from cte

结果

Name    Family
-----   ------
Aria    Karimi
Bab     Karimi
Joe     Karimi

【讨论】:

    【解决方案3】:

    试试这个:

        CREATE FUNCTION [dbo].[SplitIndex](@Delimiter varchar(20) = ' ', @Search varchar(max), @index int)
        RETURNS varchar(max)
        AS
        BEGIN
              DECLARE @ix int,
                          @pos int,
                        @rt varchar(max)
    
              DECLARE @tb TABLE (Val varchar(max), id int identity(1,1))
    
              SET @ix = 1
              SET @pos = 1
    
    
              WHILE @ix <= LEN(@search) + 1 BEGIN
    
                    SET @ix = CHARINDEX(@Delimiter, @Search, @ix)
    
                    IF @ix = 0
                          SET @ix = LEN(@Search)
                    ELSE
                          SET @ix = @ix - 1
    
                    INSERT INTO @tb
                    SELECT SUBSTRING(@Search, @pos, @ix - @pos + 1)
    
                    SET @ix = @ix + 2
                    SET @pos = @ix
              END
    
              SELECT @Rt = Val FROM @Tb WHERE id = @index
              RETURN @Rt     
        END
    

    这样使用:

    SELECT dbo.SplitIndex(' ', 'hello World', 1)
    

    将它与 Dems 的答案结合起来,你应该很高兴

    (注意如果指定的索引不存在会返回NULL)

    例如

    SELECT dbo.SplitIndex(' ', 'Hello World', 3)  
    

    将返回 NULL,因为索引 3 不存在

    虽然不确定性能如何,我只是修改了一个我已经完成的表值拆分函数,因此可能值得重写为更像 MySql 版本

    【讨论】:

    • 谢谢你,你救了我,这是最好的解决方案。以上所有使用 PARSENAME 的答案都有一个缺点,限制不超过 4 个值
    【解决方案4】:
    DECLARE @Tmp TABLE (empid INT,joined nchar(10))
    
    INSERT @Tmp SELECT 1,'1990, 1111' 
    INSERT @Tmp SELECT 2,'2000, 2222' 
    
    INSERT @Tmp SELECT 3,'1993, 3333' 
    
    INSERT @Tmp SELECT 4,'1899, 4444' 
    INSERT @Tmp SELECT 5,'1999, 5555' 
    
    INSERT @Tmp SELECT 6,'2001, 6666 ' 
    
    
    --Using PARSENAME 
    
    SELECT empid, joined,
           PARSENAME(REPLACE(joined,',','.'),2) join1, 
           PARSENAME(REPLACE(joined,',','.'),1) join2 
    FROM @Tmp
    

    【讨论】:

      【解决方案5】:

      如果您使用 C++ 编程,请这样做:

      #include <cstring>
      #include <iomanip>
      
      using namespace std;
      int main () {
      string machine[12];
      for (int i = 0; i < 12; i++) {
          if (machine[i] == "")
              machine[i] = "NULL";
      }
      
      for (int i = 0; i < 3; i++) {
          cout << setw(10) << machine[i] << setw(10) << machine[i+1] << setw(10) << machine[i+2] << endl;
      }
      return 1;
      }
      

      【讨论】:

      • 这篇文章没有c++标签,这不是猜测吗?
      • 您是否诚实地 建议通过从数据库中提取每条 记录,用 C++ 处理它,然后将所有内容推回D B? 真的
      • 对我来说听起来像是 TheDailyWTF 的恐怖故事 :)
      猜你喜欢
      • 1970-01-01
      • 2021-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多