Pivot in sql server

前端 未结 4 1332
南旧
南旧 2020-12-07 05:50

Yes I\'ve tried the code. My requirement is that user inputs Year and Month & prices are shown date-wise in columns for that year and month, with first column as Competi

相关标签:
4条回答
  • 2020-12-07 06:14

    This is a lot easier. I wrote a stored proc named pivot_query that makes PIVOT a lot easier to use for SQL Server 2005+. The source for the proc is here, some examples how to use it are here.

    For your code example:

    create table Competitors
       (
       CompetitorId      integer identity,
       Name              varchar(30)
       )
    
    insert into Competitors values ('Bobs Discount Emporium')
    go
    insert into Competitors values ('Joes Really Cheap Crap')
    go
    
    create table CompetitorDetail
       (
       Id                integer identity,
       CompetitorId      integer,
       oDate             datetime,
       Price             decimal(12,3)
       )
    
    insert into CompetitorDetail values (1, getdate()-10, 10.00)
    go
    insert into CompetitorDetail values (1, getdate()-10, 10.00)
    go
    insert into CompetitorDetail values (1, getdate()-10, 10.00)
    go
    insert into CompetitorDetail values (1, getdate()-10, 10.00)
    go
    insert into CompetitorDetail values (1, getdate()-8, 11.00)
    go
    insert into CompetitorDetail values (1, getdate()-8, 11.00)
    go
    insert into CompetitorDetail values (1, getdate()-8, 11.00)
    go
    insert into CompetitorDetail values (1, getdate()-8, 11.00)
    go
    insert into CompetitorDetail values (1, getdate()-6, 12.00)
    go
    insert into CompetitorDetail values (1, getdate()-6, 12.00)
    go
    insert into CompetitorDetail values (1, getdate()-6, 12.00)
    go
    insert into CompetitorDetail values (1, getdate()-2, 13.00)
    go
    insert into CompetitorDetail values (1, getdate()-2, 13.00)
    go
    insert into CompetitorDetail values (1, getdate()-2, 13.00)
    go
    insert into CompetitorDetail values (2, getdate()-10, 14.00)
    go
    insert into CompetitorDetail values (2, getdate()-10, 14.00)
    go
    insert into CompetitorDetail values (2, getdate()-10, 14.00)
    go
    insert into CompetitorDetail values (2, getdate()-10, 14.00)
    go
    insert into CompetitorDetail values (2, getdate()-8, 15.00)
    go
    insert into CompetitorDetail values (2, getdate()-8, 15.00)
    go
    insert into CompetitorDetail values (2, getdate()-8, 15.00)
    go
    insert into CompetitorDetail values (2, getdate()-8, 15.00)
    go
    insert into CompetitorDetail values (2, getdate()-6, 16.00)
    go
    insert into CompetitorDetail values (2, getdate()-6, 16.00)
    go
    insert into CompetitorDetail values (2, getdate()-6, 16.00)
    go
    insert into CompetitorDetail values (2, getdate()-2, 18.00)
    go
    insert into CompetitorDetail values (2, getdate()-2, 18.00)
    go
    insert into CompetitorDetail values (2, getdate()-2, 18.00)
    go
    
    declare @mySQL varchar(MAX)
    
    set @mySQL = '
    select
       c.Name,
       right(cast(month(cd.oDate) + 100 as varchar(3)),2) + ''_'' + right(cast(day(cd.oDate) + 100  as varchar(3)),2) mon_day,
       cd.Price
    from
       Competitors c
    
       JOIN CompetitorDetail cd
          on (cd.CompetitorId = c.CompetitorId )
       ';
    
    exec pivot_query @mySQL, 'Name', 'Mon_Day', 'max(Price) MaxP,min(Price) MinP'
    

    which results in:

    Name                           01_09_MaxP   01_09_MinP   01_11_MaxP   01_11_MinP   01_13_MaxP   01_13_MinP   01_17_MaxP   01_17_MinP   
    ------------------------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ 
    Bobs Discount Emporium         10.000       10.000       11.000       11.000       12.000       12.000       13.000       13.000       
    Joes Really Cheap Crap         14.000       14.000       15.000       15.000       16.000       16.000       18.000       18.000       
    

    Hope that helps!

    0 讨论(0)
  • 2020-12-07 06:20
    CASE 
    WHEN SQL Server 2005 OR 2008 THEN Use Pivot 
    WHEN Oracle THEN Use LIKE MAX(Decode(Day=1,Data,0) as Day1 and GROUP BY Day
    WHEN SQL Server 2000 THEN Use LIKE MAX(CASE WHEN Day = 1 THEN Data ELSE 0 End) As Day1 and GROUP BY Day 
    END
    
    0 讨论(0)
  • 2020-12-07 06:28

    For SQL Server 2005, 2008

    The table and some data to test

    CREATE TABLE CompetitorDetail
      ( 
       ID int
      ,CompetitorID int
      ,oDate datetime
      ,Price decimal(19, 4)
      )
    
    INSERT INTO  CompetitorDetail
          ( ID, CompetitorID, oDate, Price )
    SELECT  1, 1, '2010-01-01', 100.0 UNION
    SELECT  2, 1, '2010-01-02', 110.0 UNION
    SELECT  3, 1, '2010-01-03', 99.0 UNION
    SELECT  4, 2, '2010-01-01', 102.2 UNION
    SELECT  5, 2, '2010-01-02', 112.2 UNION
    SELECT  6, 2, '2010-01-03', 99.2 UNION
    SELECT  7, 3, '2010-01-01', 100.3 UNION
    SELECT  8, 3, '2010-01-02', 110.3 UNION
    SELECT  9, 3, '2010-01-03', 99.3 ;
    

    Start of the period and number of days

    /* First day of the peroid */
    DECLARE @StartDate datetime
        ,@NumberOfDays int
    
    SET @StartDate = '2010-01-01'
    SET @NumberOfDays = 31
    

    Dynamic columns = dynamic sql

    /* Table to compose dynamic query */
    DECLARE @qw TABLE
      ( 
       id int IDENTITY(1, 1)
      ,txt nvarchar(500)
      )
    
    /* Start composing dynamic query */
    INSERT  INTO @qw ( txt ) VALUES  ( 'SELECT' ) 
    INSERT  INTO @qw ( txt ) VALUES  ( 'CompetitorID' )
    

    Continue composing the dynamic query

    /* Helpers */
    DECLARE
      @dte datetime
     ,@str varchar(10)
     ,@i int
    
    
    /* Compose dynamic query */
    SET @i = 0
    WHILE @i < @NumberOfDays 
      BEGIN
        SET @dte = DATEADD(d, @i, @StartDate)
        SET @str = CONVERT(varchar(10), @dte, 121)  
        INSERT  INTO @qw ( txt )
                SELECT  ',MAX(CASE oDate WHEN ''' + @str + ''' THEN Price ELSE NULL END) AS [' + @str + ']'
    
        SET @i = @i + 1
      END
    
    /* Finish the dynamic query */
    INSERT  INTO @qw (txt) VALUES ( 'FROM  CompetitorDetail' )
    INSERT  INTO @qw (txt) VALUES ( 'GROUP BY CompetitorID' )
    INSERT  INTO @qw (txt) VALUES ( 'ORDER BY CompetitorID' )
    

    Concatenate into a variable and execute

    /* Create a variable with dynamic sql*/
    DECLARE @exe nvarchar(4000)
    SET @exe=''
    SELECT  @exe = @exe + txt + ' ' FROM @qw ORDER BY id
    
    
    /* execute dynamic sql */
    EXEC sp_executesql @exe
    

    Returns

    CompetitorID 2010-01-01   2010-01-02   2010-01-03   2010-01-04  ...  2010-01-31 
    ------------ ----------   ----------   ----------   ----------  ...  ---------- 
    1            100.0000     110.0000     99.0000      NULL        ...  NULL       
    2            102.2000     112.2000     99.2000      NULL        ...  NULL       
    3            100.3000     110.3000     99.3000      NULL        ...  NULL       
    
    0 讨论(0)
  • 2020-12-07 06:29

    If you'r working with Microsoft SQL-Server there is a pivot function. But the columns are defined statically, so it's use is limited. (See http://technet.microsoft.com/en-us/library/ms177410.aspx)

    There are solutions with dynamic SQL, but i solved this in the code eventually.

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