代码之家  ›  专栏  ›  技术社区  ›  T.T.T.

T-SQL选择将多行合并为一列

  •  1
  • T.T.T.  · 技术社区  · 7 年前

    我想用SQL对行进行分组,结果集如下

    命名日期
    数据112312/03/2009
    数据112415/09/2009
    数据233302/09/2010
    数据232302/11/2010
    数据267302/09/2014
    数据2444 05/01/2010

    我想将结果集分组如下:

    数据1
    2009年3月12日
    2009年9月12415日
    数据2
    2010年9月33302日
    2010年11月32302日
    67302/09/2014年
    44405/01/2010年

    使用纯SQL可以做到这一点吗?

    干杯。

    1 回复  |  直到 17 年前
        1
  •  8
  •   Cade Roux    17 年前

    GROUP BY WITH ROLLUP (你没有真正的分组-所以你实际上会 GROUP BY 每列)

    http://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html

    http://chiragrdarji.wordpress.com/2008/09/09/group-by-cube-rollup-and-sql-server-2005/

    http://databases.about.com/od/sql/l/aacuberollup.htm

    http://www.adp-gmbh.ch/ora/sql/group_by/group_by_rollup.html

    http://msdn.microsoft.com/en-us/library/bb522495.aspx

    基于利文的代码:

    DECLARE @Table TABLE (
         name varchar(32)
        ,Size integer
        ,Date datetime
        )
    
    INSERT  INTO @Table
    VALUES  ('data1', 123, GETDATE())
    INSERT  INTO @Table
    VALUES  ('data1', 124, GETDATE())
    INSERT  INTO @Table
    VALUES  ('data2', 333, GETDATE())
    INSERT  INTO @Table
    VALUES  ('data2', 323, GETDATE())
    INSERT  INTO @Table
    VALUES  ('data2', 673, GETDATE())
    INSERT  INTO @Table
    VALUES  ('data2', 444, GETDATE())
    
    SELECT  *
    FROM    (
             SELECT *
             FROM   @Table
             GROUP BY NAME
                   ,size
                   ,date
                    WITH ROLLUP
            ) AS X
    WHERE   NAME IS NOT NULL
            AND (
                 (
                  Size IS NOT NULL
                  AND Date IS NOT NULL
                 )
                 OR (
                     Size IS NULL
                     AND date IS NULL
                    )
                )
    ORDER BY NAME
           ,size
           ,date
    
        2
  •  3
  •   Jules Bartow    15 年前

    提前调整数据的形状简化了应用程序开发人员的工作,特别是如果他们所做的只是显示一个静态报表,而没有交互式的编辑、排序或分页——这种情况已经很常见了。

    Lieven的解决方案(在为其他列插入空值的同时,分别选择列,然后检查其他列的空值)是这里唯一有效的解决方案。有点。

    data1   NULL    NULL
    NULL    123 2011-05-24 19:42:29.577
    NULL    124 2011-05-24 19:42:29.577
    data2   NULL    NULL
    NULL    323 2011-05-24 19:42:29.577
    NULL    333 2011-05-24 19:42:29.577
    NULL    444 2011-05-24 19:42:29.577
    NULL    673 2011-05-24 19:42:29.577
    

    --除非您要使其为空的列已经有空值,在这种情况下,我们返回到0。再加一行。

    INSERT INTO @Table VALUES ('data2', NULL, getdate())
    

    现在再次运行查询。可怜的家伙。

    data1   NULL    NULL
    NULL    123 2011-05-24 19:53:36.437
    NULL    124 2011-05-24 19:53:36.437
    data2   NULL    NULL
    data2   NULL    2011-05-24 19:53:36.440
    NULL    323 2011-05-24 19:53:36.440
    NULL    333 2011-05-24 19:53:36.440
    NULL    444 2011-05-24 19:53:36.440
    

    Roux提出的汇总解决方案根本不起作用,至少在SQL Server中不起作用。事实上,它让事情更糟。

    data1   NULL    NULL
    data1   NULL    NULL
    data1   NULL    NULL
    data1   123 2011-05-24 20:16:26.693
    data1   124 2011-05-24 20:16:26.693
    data2   NULL    NULL
    data2   NULL    NULL
    data2   NULL    NULL
    data2   323 2011-05-24 20:16:26.693
    data2   333 2011-05-24 20:16:26.693
    data2   444 2011-05-24 20:16:26.693
    data2   673 2011-05-24 20:16:26.693
    

    Piti的ROWNUM解决方案可能在Oracle中工作(我还没有尝试过,而且似乎缺少一个开头的括号),但是使用ROW_NUMBER()代替taint的等效SQL Server代码显然也不起作用,就像我的语法和speling一样。

    SELECT 
        ROW_NUMBER() OVER(ORDER BY [name]) AS [rown]
        , name
        , ''
        , ''
    FROM @Table
    GROUP BY name
    
    UNION ALL
    
    SELECT ROW_NUMBER() OVER(ORDER BY [name]) + 1 AS [rown] , name, size, date 
    FROM @Table 
    

    生产

    数据1为空
    数据1为空
    数据1为空
    数据1 123 2011-05-24 20:16:26.693
    数据1 124 2011-05-24 20:16:26.693
    数据2为空
    数据2为空
    数据2为空
    数据2 323 2011-05-24 20:16:26.693
    数据2 333 2011-05-24 20:16:26.693
    数据2 444 2011-05-24 20:16:26.693
    数据2 673 2011-05-24 20:16:26.693
    

    作为一名软件专业人士,你的工作是确保数十亿个1和0在正确的地点、正确的顺序、正确的时间排列。你知道细节很重要,通常是个别细节。

    半个巨大的答案比没有答案更糟糕,因为它浪费了每个人的时间。所以。。。无意冒犯,因为意图是好的,但请至少测试你的“解决方案”,然后再发布为“解决方案”。

    如果我不那么卑微,我会很完美的。甚至我也在测试。

        3
  •  2
  •   Lieven Keersmaekers    17 年前

    迈克尔托德说这应该在客户端完成,但为了好玩,这是一个选择

    DECLARE @Table TABLE (name VARCHAR(32), Size INTEGER, Date DATETIME)
    
    INSERT INTO @Table VALUES ('data1', 123, getdate())
    INSERT INTO @Table VALUES ('data1', 124, getdate())
    INSERT INTO @Table VALUES ('data2', 333, getdate())
    INSERT INTO @Table VALUES ('data2', 323, getdate())
    INSERT INTO @Table VALUES ('data2', 673, getdate())
    INSERT INTO @Table VALUES ('data2', 444, getdate())
    
    INSERT INTO @Table 
    SELECT DISTINCT name, NULL, NULL
    FROM @Table
    
    SELECT 
      CASE WHEN Size IS NULL THEN Name ELSE NULL END
      , Size
      , Date
    FROM @Table
    ORDER BY Name, Size
    
        4
  •  1
  •   Cătălin Pitiș    17 年前

    可能是这样的:

    select name, size, date from
    (
    -- select only distinct rows, and empty values for size and date (header rows)
    select ROWNUM rown, name, '', ''
    from T
    group by name
    order by name
    
    union all
    
    -- select all data (non-header records)
    select ROWNUM+1 rown, name, size, date 
    from T 
    order by name
    )
    order by name, rown
    

    说明: 首先从联合中选择选择组标题的记录。它按名称对结果进行排序。行号给出了顺序。 第二个选择从联合中选择组头的所有记录。它按名称对结果进行排序,行号给出顺序。 工会把所有的信息汇总起来。第二个select的ROWNUM+1确保头的记录(从第一个select开始)在详细记录之前排序。

    现在。。。你需要做什么,我没有恢复那么多的SQL来知道怎么做。。。当大小写或日期为“”时,将“”作为名称放在主选择中(使用case/swich操作)。这里需要一些帮助:)。

    正如观察到的那样,在所提供的SQL中,ROWNUM是一个特殊的列,它为select提供行号(例如,请参见Oracle)。

    查询只是作为原则显示的,我不能百分之百确定它是否有效。

    更新: ... 这是一个解决方案草图。但我仍然认为这是一个格式化问题,而不是SQL问题。

        5
  •  1
  •   Umair Anwar    9 年前

    您可以使用两个查询,然后在应用程序代码中分组/格式化。

    第一个查询

    SELECT DISTINCT(name) AS group_name FROM TABLE ORDER BY name LIMIT 5;
    

    第二个查询

    SELECT size, date FROM TABLE WHERE name IN ('comma separated group_name values from firstQueryResult');
    

    应用程序代码

    for every row in firstQueryResult{
        group_array[group_name] = secondQueryResult;
    }
    

    生成的组数组将如下所示:;

    data1
      123  12/03/2009
      124  15/09/2009
    data2
      333  02/09/2010
      323  02/11/2010
      673  02/09/2014
      444  05/01/2010