Sql group rows with same value, and put that value into header?

前端 未结 5 1944
梦毁少年i
梦毁少年i 2020-12-11 04:50

I want to group rows with SQL, my result set is following

name  size  date
data1  123  12/03/2009
data1 &nb

相关标签:
5条回答
  • 2020-12-11 05:16

    Michael Todd is definitly right when he says this should be done on the client side but for the fun of it, this is one option

    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
    
    0 讨论(0)
  • 2020-12-11 05:17

    There might be something like:

    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
    

    Explanation: First select from the union selects the records for the group header. It sorts the results by name. The row number gives the order. Second select from the union selects all the records for the group header. It sorts the results by name, and the row number gives the order. The union put all the information together. ROWNUM+1 for the second select ensures that records for the header (from the first select) are ordered before the detailed records.

    Now... what you need to do and I don't recover so much SQL to know how to do it... is to put '' for name when size or date are '', in the main select (with a case/swich operation). Some help is needed here :).

    Just as an observation, in the provided SQL, ROWNUM is a special column that provides the row number for a select (see Oracle for example).

    The query is displayed just as principle, I am not 100% sure it works.

    Update: ... thats a solution sketch. But I still believe this is a formatting problem, and not an SQL problem.

    0 讨论(0)
  • 2020-12-11 05:25

    You can use two queries and then group/format in the application code.

    First query

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

    Second query

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

    Application code

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

    The resulting group_array will be like;

    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
    
    0 讨论(0)
  • 2020-12-11 05:31

    GROUP BY WITH ROLLUP (you're not really grouping - so you would actaully GROUP BY every column)

    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

    Based on Lieven's code:

    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
    
    0 讨论(0)
  • 2020-12-11 05:32

    Shaping the data ahead of time simplifies things for the application developer, especially if all they're doing is displaying a static report with no interactive editing, sorting, or paging --a common enough occurrence.

    Lieven's solution (selecting the columns distinctively while inserting nulls for other columns, then checking for the nulls of the other columns) is the only solution here that actually works. Kind of.

    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
    

    --unless the column you're nullalizing already has nulls, in which case we're back to square 0. Add one more row.

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

    Now run the query again. Bummer dude.

    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's proposed ROLLUP solution doesn't work at all, at least not in SQL Server. Actually, it makes things more worserer.

    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 solution may work in Oracle (I haven't tried it and there appears to a missing beginning parentheses), but the equivalent SQL Server code using ROW_NUMBER() OVER definitely taint working no good neither --about as well as my grammer and 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 
    

    produces

    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
    

    As a software professional your job is to ensure billions of 1s and 0s line up at the right place, in the right order, at the right time. You know the details, often times down to an individual bit, are important.

    A half vast answer is worse than no answer at all because it wastes everyone's time. So... no offense intended because intentions are good, but please at least test your "solution" before posting it as a "solution".

    I would be perfect if I weren't so darned humble. And even I test.

    0 讨论(0)
提交回复
热议问题