2010-01-14 4 views
1

Да Я пробовал код. Мое требование состоит в том, что пользователь вводит год и месяц & цены указаны по дате в столбцах за этот год и месяц, причем первый столбец соответствует CompetitorID. Я хочу, чтобы мой результат как:Pivot in sql server

 
Competitors | day1 | day2 | day3 | day4 ..............|day31 
================================================================ 
competitor 1| Price | Price | price | price..............|price 
competitor 2| Price | Price | price | price..............|price 
competitor 3| Price | Price | price | price..............|price 
competitor 4| Price | Price | price | price..............|price 

Моя структура таблицы:

COMPETITORDETAIL (ID, CompetitorID, oDate, Price)

+0

Вы хотите показать это только в течение определенного месяца или за все месяцы/дни? Должен ли он показывать столбцы в течение дней, когда нет записей? Будет ли это динамическим, или для фиксированных столбцов и дат * (например, вы хотите видеть только значения за январь 2009 года) *? Вам нужно показать некоторые примерные данные и ожидаемый результат. –

+0

Я показал результат. Пользователь будет вводить год и месяц, и запрос приведет к вышеуказанному формату, то есть конкурентам в первом столбце и остальной части столбцов будут даты (от 1 до 31) за этот год и месяц. – hotcoder

ответ

2

Это намного проще. Я написал сохраненную процедуру с именем pivot_query, что делает PIVOT намного проще в использовании для SQL Server 2005+. Источником для процесса является here, некоторые примеры его использования - here.

Для примера кода:

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' 

что приводит:

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  

Надежда, что помогает!

0

Если you'r работает с Microsoft SQL-Server, есть функция поворота. Но столбцы определяются статически, поэтому использование ограничено. (См. http://technet.microsoft.com/en-us/library/ms177410.aspx)

Есть решения с динамическим SQL, но в конце концов я решил это в коде.

0
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

Для SQL Server 2005, 2008

таблицы и некоторые данные для тестирования

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 ; 

Начала периода и количества дней

/* First day of the peroid */ 
DECLARE @StartDate datetime 
    ,@NumberOfDays int 

SET @StartDate = '2010-01-01' 
SET @NumberOfDays = 31 

Динамических столбцов = динамических 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') 

Продолжить слагающих динамический запрос

/* 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 в переменную и выполнить

/* 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 

Возвращает

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