代码之家  ›  专栏  ›  技术社区  ›  paweloque

在sql中concat所有列值

  •  25
  • paweloque  · 技术社区  · 15 年前

    如何将SQL查询返回的不同行中的所有列值浓缩为一个值?这是一个例子:

    查询返回:

    FOO
    ------
    RES1
    
    RES2
    
    RES3
    

    现在我想得到如下结果:

    FOOCONCAT
    -----
    RES1RES2RES3
    

    在sql中有什么方法可以做到这一点吗?

    12 回复  |  直到 15 年前
        1
  •  47
  •   Quassnoi    15 年前

    SQL Server :

    SELECT  col1 AS [text()]
    FROM    foo
    FOR XML PATH ('')
    

    MySQL :

    SELECT  GROUP_CONCAT(col1 SEPARATOR '')
    FROM    foo
    

    PostgreSQL :

    SELECT  array_to_string
            (
            ARRAY
            (
            SELECT  col1
            FROM    foo
            ), ''
            )
    

    Oracle :

    SELECT  *
    FROM    (
            SELECT  col1, ROW_NUMBER() OVER(ORDER BY 1) AS rn
            FROM    foo
            MODEL
            DIMENSION BY
                    (rn)
            MEASURES
                    (col1, col1 AS group_concat, 0 AS mark)
            RULES UPDATE (
                    group_concat[rn > 1] =  group_concat[CV() - 1] || col1[CV()],
                    mark[ANY] = PRESENTV(mark[CV() + 1], 0, 1)
                    )
            )
    WHERE   mark = 1
    
        2
  •  9
  •   devio    15 年前

    卡西诺的甲骨文解决方案令人印象深刻,但我 found simpler 使用sys_connect_by_path()而不是模型魔术的。

    SELECT REPLACE(MAX(SYS_CONNECT_BY_PATH(foo, '/')), '/', '') conc
    FROM (
        SELECT T_FOO.*, ROW_NUMBER() OVER (ORDER BY FOO) R FROM T_FOO
    )
    START WITH r=1
    CONNECT BY PRIOR r = r-1;
    
        3
  •  3
  •   John McLusky    15 年前

    假设它是一个包含多个值的列,这种方法适用于ms sql server(我不能代表其他系统)。

    declare @result varchar(max)
    set @result = ''
    
    select @result = @result + RES
    from (query goes here)
    
        4
  •  3
  •   ʞɔıu    15 年前

    mysql方式:

    select group_concat(somecolumn separator '') from sometable
    
        5
  •  1
  •   Steve Broberg    15 年前

    这是您正在寻找的答案;我感觉解决方案就在connect by操作中,我之前没有使用sys_connect_by_path伪列(它在树中显示节点的完整路径,用“/”分隔节点名称)。假设之前的一组“foo”值是表中的多行,按列“mykey”分组,例如:

    myKey    foo
    -------- ----------
    group 1  apple
    group 1  orange
    group 1  pear
    group 2  ape
    group 2  bear
    group 2  kitten
    

    您可以将数据视为一个树模式,并假设每个组的值表示沿分支向下的节点。在这种情况下,你应该这样做:

      SELECT myKey
           , SUBSTR(MAX(REPLACE(SYS_CONNECT_BY_PATH(foo, '/')
                               ,'/'
                               ,' '
                               )
                       )
                   ,2
                   ) FooConcat
        FROM ( SELECT MyKey
                    , Foo
                    , row_number() OVER (Partition by myKey order by myKey) NodeDepth
                 FROM MyTable
             )
       START WITH NodeDepth = 1
     CONNECT BY PRIOR myKey = myKey
         AND PRIOR NodeDepth = NodeDepth -1
    GROUP BY myKey
    ;
    

    当然,连接值的顺序是随机的;如果您的表有另一列(“bar”)可以用作升序和连续的排序字段,那么您可以不使用子查询(它只存在于向树放置一个虚构的深度)并使用表direc把nodedepth换成bar。

        6
  •  1
  •   esengineer    13 年前

    编辑: 因为8.4.0版本cubrid提供了 90% compatibility 使用MySQL。因此,它支持 GROUP_CONCAT 其语法与mysql相似:

    CREATE TABLE t(i int);
    INSERT INTO t VALUES (4),(2),(3),(6),(1),(5);
    
    SELECT GROUP_CONCAT(i*2+1 ORDER BY 1 SEPARATOR '') FROM t;
    
    group_concat(i*2+1 order by 1 separator '')
    ======================
      '35791113'
    

    相当强大,不是吗?下面是一个 alternative solution 在古巴本土支持。

    SELECT MAX(SYS_CONNECT_BY_PATH(s_name, '')) AS conc_s_name
    FROM (
         SELECT ROWNUM AS r, s_name FROM code
    ) AS res
    START WITH r = 1
    CONNECT BY PRIOR r = r - 1;
    

    有趣的是,这种在cubrid中连接不同行列值的方法几乎与@devio提供的oracle方法相同。不过,在库布里德看来要容易一点。

        7
  •  0
  •   D'Arcy Rittich    15 年前
    select cast(res1 as varchar)+cast(res2 as varchar)+cast(res3 as varchar) as fooconcat from foo
    

    如果列已经是字符串,则不需要转换,只需执行以下操作:

    select res1 + res2 + res3  as fooconcat from foo
    

    对于来自多行的数据,使用 PIVOT .

        8
  •  0
  •   user110714    15 年前

    串接字符串取决于您正在使用的数据库(您在问题中没有提到什么版本,所以这里是…)。

    在Oracle和DB2中,您可以使用 CONCAT 功能… CONCAT(string, string)

    SQL Server您可以使用“+”运算符… string1 + string2 + string3

    在mysql中 CONCAT(string, string... n_string)

    最后在postgresql中 TEXTCAT(string, string)

    …我从这本很酷的书中得到这个,我坐在我的桌子上,O'Reilly的SQL袖珍指南…过来看!

    :)

        9
  •  0
  •   Steve Broberg    15 年前

    这可能不是你想要的,但我在过去有过这样的好运气:

    SELECT      MAX(DECODE(fookey, 1, foo, NULL))
             || MAX(DECODE(fookey, 2, foo, NULL))
             || MAX(DECODE(fookey, 3, foo, NULL))
             || MAX(DECODE(fookey, 4, foo, NULL))
           , groupingvalue
        FROM mytable
    GROUP BY groupingvalue;
    

    它是独立于平台的,当foo有一个任意但数量有限的值,并且它们基于一些其他键值时,它可以很好地工作。例如,如果您有一个发票表,并且希望在一行中看到发票的所有行时间,并且您有一个5行项目的上限,则如下所示:

    SELECT      MAX(DECODE(lineno, 1, foo, NULL))
             || ', '
             || MAX(DECODE(lineno, 2, foo, NULL))
             || ', '
             || MAX(DECODE(lineno, 3, foo, NULL))
             || ', '
             || MAX(DECODE(lineno, 4, foo, NULL))
             || ', '
             || MAX(DECODE(lineno, 5, foo, NULL))
           , invoiceid
        FROM lineitem
    GROUP BY invoiceid;
    
        10
  •  0
  •   Kristy Welsh    10 年前

    SQL Server 2008 R2:

    declare @ColumnNameList VARCHAR(MAX)
    
    
     SELECT @ColumnNameList  = COALESCE(@ColumnNameList +',' ,'') + ColumnName 
                         FROM 
                           <<table name>>
    
    select @ColumnNameList 
    
        11
  •  0
  •   RobC Manuel Gonzalez    6 年前

    我找到了答案 How to concatenate all the records in a column returned by a query into one varchar string in T-SQL?

    declare @s varchar(8000)
    select @s = coalesce(@s + col, col) from tbl
    

    这应该可以解决

        12
  •  -2
  •   Danish    14 年前

    从[表]中选择([col1]+'、'+[col2]+'、'+[col3]+'、'+[col4])作为[mycol]