SQL Server Forums
Profile | Register | Active Topics | Members | Search | Forum FAQ
 
Register Now and get your question answered!
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Need help about Cross Tab
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic  

sqllover
Constraint Violating Yak Guru

India
334 Posts

Posted - 03/08/2014 :  23:53:52  Show Profile  Reply with Quote
Hi,

Working with Sqlserver 2008 R2.

Below is my working code for converting rows into columns.

REATE Procedure [dbo].[GetReports]
(
	@Year		int = null,
	@Month	    int = null
)
AS

BEGIN

if OBJECT_ID('#DateRange') is not null drop table #DateRange

 declare @cols nvarchar(4000);
 DECLARE @Query nvarchar(4000);
 DECLARE @fromdate DATE,@todate DATE,@DaysCount int;

 
--set @Month = 8
--set @Year = 2013          



IF(@Year is not null and @Year >0 and @Month is not null and @Month >0)

BEGIN
 SELECT @fromdate = DATEADD(MONTH, (@year - 1900) * 12 + @month - 1, '1900-01-01')
	,@todate = DATEADD(DAY, - 1, DATEADD(MONTH, (@year - 1900) * 12 + @month, '1900-01-01'))
	select @DaysCount = datediff(dd,dateadd(dd, 1-day(@fromdate),@fromdate), dateadd(m,1,dateadd(dd, 1-day(@fromdate),@fromdate)))
	
	
	 select @cols = coalesce(@cols +',','') + '[' + [DATE] + ']' from (

			SELECT	[DATE]	= CONVERT(nVARCHAR(100), DATEADD(DD, n, @fromdate), 121)
			FROM	(
					VALUES (0), (1), (2), (3), (4), (5), (6),(7), (8), (9), (10), (11), (12), (13),
					(14), (15), (16), (17), (18), (19),(20), (21), (22), (23), (24), (25),
					(26), (27), (28), (29), (30),(31)
				) num (n) WHERE n < @DaysCount ) d

END

IF(@month > 0 and @Year > 0 )
 BEGIN
				 ;WITH DateRange(Date) AS
					(
						SELECT
							@fromdate as Date
						UNION ALL
						SELECT
							DATEADD(day, 1, Date) as Date
						FROM
							DateRange
						WHERE
							Date <= @todate
					)
				    
				SELECT date into #DateRange from DateRange
				 
				 set @Query = 'SELECT * from
								 ( 			 
				 select Name as [Name],mydate as [Date_Of_Day] ,COALESCE ( cast(Records as varchar) , cast((cast(newdate as date)) as varchar)) as [Records] from(   
					SELECT c.Name,Date as mydate,c.GrocessaryStoredelay as delay  
					,case when b.Records is null then DATEADD(DAY, (nullif(c.GrocessaryStoreDelay,0) + nullif(DataFrequency,0)), a.Date) else convert(datetime,0,101) end as newdate,b.Records
					FROM #DateRange a
				Cross join
				dbo.GrocessaryStore c
				Left join
				dbo.Month_Report b
				On c.StoreID = b.StoreID
				And a.date = b.Date_Of_Day
				) aa where aa.delay is not null) 
								  as p PIVOT ( max([records]) FOR [Date_Of_Day] 
											  IN ('+ @cols+')) AS pvt  order by pvt.Name' 			

END

                    
Print @Query;
EXEC sp_executesql @Query 

END


Is is possible to achieve this with Cross Tabs? I am learning Pivot Vs Cross Tab for the performance.
But on my sample i am struggling to implement cross tab. Can any one suggest me is it possible to create Cross Tab on my sample. If yes please post some modified query based on my sample

Edited by - sqllover on 03/10/2014 12:29:13

sqllover
Constraint Violating Yak Guru

India
334 Posts

Posted - 03/09/2014 :  12:31:59  Show Profile  Reply with Quote
Sample Sta and Expected Result:


Table: GrocessaryStore  
IdGrocessaryStore int identity(1,1) Primary key,
Name varchar(50),GrocessaryStoreDelay int, DataFrequency int, StoreID varchar(20)

With GrocessaryStore  as (
select 1 as IdGrocessaryStore,'WallMart' as Name,10 as GrocessaryStoreDelay, 2 as DataFrequency, 100 as StoreID union all
select 2 as IdGrocessaryStore,'Kelly' as Name,13 as GrocessaryStoreDelay, 1 as DataFrequency, 101 as StoreID union all
select 3 as IdGrocessaryStore,'Subway' as Name,12 as GrocessaryStoreDelay, 3 as DataFrequency, 102 as StoreID union all
select 4 as IdGrocessaryStore,'Dominos' as Name,14 as GrocessaryStoreDelay, 5 as DataFrequency, 103 as StoreID union all
select 5 as IdGrocessaryStore,'Pizzahut' as Name,15 as GrocessaryStoreDelay, 3 as DataFrequency, 104 as StoreID union all
select 6 as IdGrocessaryStore,'BigY' as Name,12 as GrocessaryStoreDelay, 8 as DataFrequency, 105 as StoreID union all
select 7 as IdGrocessaryStore,'Target' as Name,19 as GrocessaryStoreDelay, 3 as DataFrequency, 106 as StoreID union all
select 8 as IdGrocessaryStore,'FishingNet' as Name,20 as GrocessaryStoreDelay, 14 as DataFrequency, 107 as StoreID )

Table : Month_Report

IDReport int identity(1,1) primary key,StoreID varchar(20),Date_Of_Day date, Records int

with  Month_Report as (
 select 1 as IDReport, 100 as StoreID,'2014-02-01' as Date_Of_Day,1500 as Records union all
 select 2 as IDReport, 100 as StoreID,'2014-02-02' as Date_Of_Day,1200 as Records union all
 select 3 as IDReport, 100 as StoreID,'2014-02-03' as Date_Of_Day,1300 as Records union all
 select 4 as IDReport, 100 as StoreID,'2014-02-04' as Date_Of_Day,1800 as Records union all
 select 5 as IDReport, 100 as StoreID,'2014-02-05' as Date_Of_Day,1100 as Records union all
 select 6 as IDReport, 100 as StoreID,'2014-02-06' as Date_Of_Day,1000 as Records union all
 select 7 as IDReport, 100 as StoreID,'2014-02-07' as Date_Of_Day,1200 as Records union all
 select 8 as IDReport, 100 as StoreID,'2014-02-08' as Date_Of_Day,1400 as Records union all
 select 9 as IDReport, 100 as StoreID,'2014-02-09' as Date_Of_Day,1800 as Records union all
 select 10 as IDReport, 100 as StoreID,'2014-02-10' as Date_Of_Day,1900 as Records union all
 select 11 as IDReport, 100 as StoreID,'2014-02-11' as Date_Of_Day,1700 as Records union all
 select 12 as IDReport, 100 as StoreID,'2014-02-12' as Date_Of_Day,1000 as Records union all
 select 13 as IDReport, 100 as StoreID,'2014-02-13' as Date_Of_Day,1200 as Records union all
 select 14 as IDReport, 100 as StoreID,'2014-02-14' as Date_Of_Day,1700 as Records union all
 select 15 as IDReport, 100 as StoreID,'2014-02-15' as Date_Of_Day,NULL as Records union all   
 select 16 as IDReport, 100 as StoreID,'2014-02-16' as Date_Of_Day, 1000 as Records union all 
  select 17 as IDReport, 101 as StoreID,'2014-02-01' as Date_Of_Day,2500 as Records union all
 select 18 as IDReport, 101 as StoreID,'2014-02-02' as Date_Of_Day,1200 as Records union all
 select 19 as IDReport, 101 as StoreID,'2014-02-03' as Date_Of_Day,NULL as Records union all
 select 20 as IDReport, 101 as StoreID,'2014-02-04' as Date_Of_Day,1800 as Records union all
 select 21 as IDReport, 101 as StoreID,'2014-02-05' as Date_Of_Day,2100 as Records union all
 select 22 as IDReport, 101 as StoreID,'2014-02-06' as Date_Of_Day,1000 as Records union all
 select 23 as IDReport, 101 as StoreID,'2014-02-07' as Date_Of_Day,2200 as Records union all
 select 24 as IDReport, 101 as StoreID,'2014-02-08' as Date_Of_Day,1400 as Records union all
 select 25 as IDReport, 101 as StoreID,'2014-02-09' as Date_Of_Day,3800 as Records union all
 select 26 as IDReport, 101 as StoreID,'2014-02-10' as Date_Of_Day,3900 as Records union all
 select 27 as IDReport, 101 as StoreID,'2014-02-11' as Date_Of_Day,1700 as Records union all
 select 28 as IDReport, 101 as StoreID,'2014-02-12' as Date_Of_Day,1000 as Records union all
 select 29 as IDReport, 101 as StoreID,'2014-02-13' as Date_Of_Day,1200 as Records union all
 select 30 as IDReport, 101 as StoreID,'2014-02-14' as Date_Of_Day,1700 as Records union all
 select 31 as IDReport, 101 as StoreID,'2014-02-15' as Date_Of_Day,1600 as Records union all 
 select 32 as IDReport, 101 as StoreID,'2014-02-16' as Date_Of_Day,1800 as Records union all
 select 33 as IDReport, 101 as StoreID,'2014-02-17' as Date_Of_Day,2700 as Records union all
 select 34 as IDReport, 101 as StoreID,'2014-02-18' as Date_Of_Day,2600 as Records 
 
)


Please execute the below two select queries and combine them as expected result. The output is two rows. Hope my sample is clear.


Expected Result:


select 'WallMart' as Name,1500 as [2014-02-01],1200 as [2014-02-02],1300 as [2014-02-03],1800 as [2014-02-04],1100 as [2014-02-05],1000 as [2014-02-06],1200 as [2014-02-07],
1400 as [2014-02-08],1800 as [2014-02-09],1900 as [2014-02-10],1700 as [2014-02-11],1000 as [2014-02-12],1200 as [2014-02-13],1700 as [2014-02-14],
'2014-02-27' as [2014-02-15],1000 as [2014-02-16],
'2014-03-01' as [2014-02-17],'2014-03-02' as [2014-02-18],'2014-03-03' as [2014-02-19],'2014-03-04' as [2014-02-20],'2014-03-02' as [2014-02-21],'2014-03-06' as [2014-02-22],'2014-03-07' as [2014-02-23],
'2014-03-08' as [2014-02-24],'2014-03-09' as [2014-02-25],'2014-03-10' as [2014-02-26],'2014-03-11' as [2014-02-27],'2014-03-12' as [2014-02-28]

select 'Kelly' as Name,2500 as [2014-02-01],1200 as [2014-02-02],'2014-02-17' as [2014-02-03],1800 as [2014-02-04],2100 as [2014-02-05],1000 as [2014-02-06],2200 as [2014-02-07],
1400 as [2014-02-08],3800 as [2014-02-09],3900 as [2014-02-10],1700 as [2014-02-11],1000 as [2014-02-12],1200 as [2014-02-13],1700 as [2014-02-14],
1600 as [2014-02-15],1800 as [2014-02-16],
2700 as [2014-02-17],2600 as [2014-02-18],'2014-03-05' as [2014-02-19],'2014-03-06' as [2014-02-20],'2014-03-07' as [2014-02-21],'2014-03-08' as [2014-02-22],'2014-03-09' as [2014-02-23],
'2014-03-10' as [2014-02-24],'2014-03-11' as [2014-02-25],'2014-03-12' as [2014-02-26],'2014-03-13' as [2014-02-27],'2014-03-14' as [2014-02-28]



As i said the The proc i posted on my previous post was working fine. Thought of achieving that through Cross Tabs which will help me to learn about it. please help me on this
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

Sweden
30265 Posts

Posted - 03/10/2014 :  16:05:04  Show Profile  Visit SwePeso's Homepage  Reply with Quote
You can make the procedure much more efficient by NOT CROSS JOINING...
CREATE PROCEDURE dbo.GetReports
(
	@Year SMALLINT = NULL,
	@Month TINYINT = NULL
)
AS

SET NOCOUNT ON;

IF @Year IS NULL OR @Year NOT BETWEEN 1900 AND 9999
	RETURN

IF @Month IS NULL OR @Month NOT BETWEEN 1 AND 12
	RETURN

DECLARE @FromDate DATETIME = DATEADD(MONTH, 12 * @Year - 22801 + @Month, '19000101'),
	@ToDate DATETIME = DATEADD(MONTH, 12 * @Year - 22800 + @Month, '18991231'),
	@SQL VARCHAR(MAX);

-- Get the data more efficient
SELECT		c.Name AS theStore,
		CAST(b.Date_Of_Day AS DATE) AS theDate,
		MAX(CASE
			WHEN b.Records IS NOT NULL THEN CAST(b.Records AS VARCHAR(100))
			ELSE CONVERT(CHAR(8), DATEADD(DAY, c.GrocessaryStoreDelay + NULLIF(c.DataFrequency, 0), b.Date_Of_Day), 112)
		END) AS theValue
INTO		#Data
FROM		dbo.GrocessaryStore AS c
LEFT JOIN	dbo.Month_Report AS b ON b.StoreID = c.StoreID
			AND b.Date_Of_Day BETWEEN @FromDate AND @ToDate
WHERE		c.GrocessaryStoreDelay > 0
GROUP BY	c.Name,
		b.Date_Of_Day;

-- Do the cross tab
SET	@SQL = 'SELECT theStore AS Name';

SET	@SQL +=	(
			SELECT		',MAX(CASE WHEN theDate = ' + QUOTENAME(theDate, '''') + ' THEN theValue ELSE '''' END) AS ' + QUOTENAME(theDate)
			FROM		(
						SELECT	CONVERT(CHAR(8), DATEADD(DAY, Number, @FromDate), 112) AS theDate,
							Number
						FROM	master.dbo.spt_values
						WHERE	[type] = 'P'
							AND Number < DAY(@ToDate)		
					) AS d
			ORDER BY	Number
			FOR XML		PATH('')
		);

SET	@SQL += ' FROM #Data GROUP BY theStore ORDER BY theStore;';

EXEC	(@SQL);
GO



Microsoft SQL Server MVP, MCT, MCSE, MCSA, MCP, MCITP, MCTS, MCDBA
Go to Top of Page

sqllover
Constraint Violating Yak Guru

India
334 Posts

Posted - 03/10/2014 :  20:17:06  Show Profile  Reply with Quote
Hi SwePeso,

Thank you so much for your time on this. I tried to create the proc as you suggested and ran the proc. But it shows empty data for the dates column if there is no records. But as per my logic it should calculate the delay + frequency and to be added with date column. But it's not happening. Are we missing something? please suggest me

If you could execute the expected result of my sample if it has records it will show the records else it will add the date(from column)+ delay + frequency and will be displayed on the row cell.

also getting warning message as
Warning: Null value is eliminated by an aggregate or other SET operation.

Please help me on this
Go to Top of Page

sqllover
Constraint Violating Yak Guru

India
334 Posts

Posted - 03/11/2014 :  09:22:44  Show Profile  Reply with Quote
Hi Swepeso,

The only place i am struck up with on the sample is


SET	@SQL +=	(
			SELECT		',MAX(CASE WHEN theDate = ' + QUOTENAME(theDate, '''') + ' THEN theValue ELSE 0 END) AS ' + QUOTENAME(theDate)
			FROM		(
						SELECT	CONVERT(CHAR(8), DATEADD(DAY, Number, @FromDate), 112) AS theDate,
							Number
						FROM	master.dbo.spt_values
						WHERE	[type] = 'P'
							AND Number < DAY(@ToDate)		
					) AS d
			ORDER BY	Number
			FOR XML		PATH('')
		);


On the case instead of 0 i want to display the calculated date logic


DATEADD(DAY, (nullif(c.GrocessaryStoreDelay,0) + nullif(DataFrequency,0)), a.Date) else convert(datetime,0,101)


But if i add this i am getting error. Any suggestion or changes on the code please guide me
Go to Top of Page

sqllover
Constraint Violating Yak Guru

India
334 Posts

Posted - 03/11/2014 :  21:27:29  Show Profile  Reply with Quote
This is how achieved.

Thanks Peso for your help.,

CREATE TABLE #GrocessaryStore 
(  
    IdGrocessaryStore int Primary key
    ,Name varchar(50)
    ,GrocessaryStoreDelay int
    ,DataFrequency int
    ,StoreID varchar(20)
);    

With GrocessaryStore  as 
(
    select 1 as IdGrocessaryStore,'WallMart' as Name,10 as GrocessaryStoreDelay, 2 as DataFrequency, 100 as StoreID union all
    select 2 as IdGrocessaryStore,'Kelly' as Name,13 as GrocessaryStoreDelay, 1 as DataFrequency, 101 as StoreID union all
    select 3 as IdGrocessaryStore,'Subway' as Name,12 as GrocessaryStoreDelay, 3 as DataFrequency, 102 as StoreID union all
    select 4 as IdGrocessaryStore,'Dominos' as Name,14 as GrocessaryStoreDelay, 5 as DataFrequency, 103 as StoreID union all
    select 5 as IdGrocessaryStore,'Pizzahut' as Name,15 as GrocessaryStoreDelay, 3 as DataFrequency, 104 as StoreID union all
    select 6 as IdGrocessaryStore,'BigY' as Name,12 as GrocessaryStoreDelay, 8 as DataFrequency, 105 as StoreID union all
    select 7 as IdGrocessaryStore,'Target' as Name,19 as GrocessaryStoreDelay, 3 as DataFrequency, 106 as StoreID union all
    select 8 as IdGrocessaryStore,'FishingNet' as Name,20 as GrocessaryStoreDelay, 14 as DataFrequency, 107 as StoreID 
)
INSERT INTO #GrocessaryStore
SELECT * FROM GrocessaryStore;

CREATE TABLE #Month_Report
(
    IDReport int  primary key
    ,StoreID varchar(20)
    ,Date_Of_Day date
    , Records int
);

WITH Month_Report as 
(
    select 1 as IDReport, 100 as StoreID,'2014-02-01' as Date_Of_Day,1500 as Records union all
    select 2 as IDReport, 100 as StoreID,'2014-02-02' as Date_Of_Day,1200 as Records union all
    select 3 as IDReport, 100 as StoreID,'2014-02-03' as Date_Of_Day,1300 as Records union all
    select 4 as IDReport, 100 as StoreID,'2014-02-04' as Date_Of_Day,1800 as Records union all
    select 5 as IDReport, 100 as StoreID,'2014-02-05' as Date_Of_Day,1100 as Records union all
    select 6 as IDReport, 100 as StoreID,'2014-02-06' as Date_Of_Day,1000 as Records union all
    select 7 as IDReport, 100 as StoreID,'2014-02-07' as Date_Of_Day,1200 as Records union all
    select 8 as IDReport, 100 as StoreID,'2014-02-08' as Date_Of_Day,1400 as Records union all
    select 9 as IDReport, 100 as StoreID,'2014-02-09' as Date_Of_Day,1800 as Records union all
    select 10 as IDReport, 100 as StoreID,'2014-02-10' as Date_Of_Day,1900 as Records union all
    select 11 as IDReport, 100 as StoreID,'2014-02-11' as Date_Of_Day,1700 as Records union all
    select 12 as IDReport, 100 as StoreID,'2014-02-12' as Date_Of_Day,1000 as Records union all
    select 13 as IDReport, 100 as StoreID,'2014-02-13' as Date_Of_Day,1200 as Records union all
    select 14 as IDReport, 100 as StoreID,'2014-02-14' as Date_Of_Day,1700 as Records union all
    select 15 as IDReport, 100 as StoreID,'2014-02-15' as Date_Of_Day,NULL as Records union all   
    select 16 as IDReport, 100 as StoreID,'2014-02-16' as Date_Of_Day, 1000 as Records union all 
    select 17 as IDReport, 101 as StoreID,'2014-02-01' as Date_Of_Day,2500 as Records union all
    select 18 as IDReport, 101 as StoreID,'2014-02-02' as Date_Of_Day,1200 as Records union all
    select 19 as IDReport, 101 as StoreID,'2014-02-03' as Date_Of_Day,NULL as Records union all
    select 20 as IDReport, 101 as StoreID,'2014-02-04' as Date_Of_Day,1800 as Records union all
    select 21 as IDReport, 101 as StoreID,'2014-02-05' as Date_Of_Day,2100 as Records union all
    select 22 as IDReport, 101 as StoreID,'2014-02-06' as Date_Of_Day,1000 as Records union all
    select 23 as IDReport, 101 as StoreID,'2014-02-07' as Date_Of_Day,2200 as Records union all
    select 24 as IDReport, 101 as StoreID,'2014-02-08' as Date_Of_Day,1400 as Records union all
    select 25 as IDReport, 101 as StoreID,'2014-02-09' as Date_Of_Day,3800 as Records union all
    select 26 as IDReport, 101 as StoreID,'2014-02-10' as Date_Of_Day,3900 as Records union all
    select 27 as IDReport, 101 as StoreID,'2014-02-11' as Date_Of_Day,1700 as Records union all
    select 28 as IDReport, 101 as StoreID,'2014-02-12' as Date_Of_Day,1000 as Records union all
    select 29 as IDReport, 101 as StoreID,'2014-02-13' as Date_Of_Day,1200 as Records union all
    select 30 as IDReport, 101 as StoreID,'2014-02-14' as Date_Of_Day,1700 as Records union all
    select 31 as IDReport, 101 as StoreID,'2014-02-15' as Date_Of_Day,1600 as Records union all 
    select 32 as IDReport, 101 as StoreID,'2014-02-16' as Date_Of_Day,1800 as Records union all
    select 33 as IDReport, 101 as StoreID,'2014-02-17' as Date_Of_Day,2700 as Records union all
    select 34 as IDReport, 101 as StoreID,'2014-02-18' as Date_Of_Day,2600 as Records 
)
INSERT INTO #Month_Report
SELECT * FROM Month_Report;

DECLARE @Year INT = 2014
    ,@Month INT = 02;

DECLARE @FromDate DATETIME = DATEADD(month, @Month-1, DATEADD(year, @year-1900, 0)),
	@ToDate DATETIME = DATEADD(month, @Month, DATEADD(year, @year-1900, 0))-1;

DECLARE @SQL NVARCHAR(MAX)
    ,@SQLParms NVARCHAR(MAX) = '@FromDate DATE, @ToDate DATE';

WITH Dates AS
(
    SELECT d=CONVERT(CHAR(10), @FromDate + n, 120)
    FROM 
    (
        SELECT n=0 UNION ALL 
        SELECT TOP (DATEDIFF(day, @FromDate, @ToDate)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
        FROM (VALUES(0),(0),(0),(0)) a (n1)
        CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0)) b(n2)
    ) a
)
SELECT @SQL = N'
SELECT Name' + 
(
    SELECT ', [' + d + ']=ISNULL(CAST(MAX(CASE WHEN Date_Of_Day=''' + d +''' THEN CAST(Records AS VARCHAR(10)) END) AS VARCHAR(10)), ' +
        'CONVERT(VARCHAR(10), DATEADD(day, MAX(GrocessaryStoreDelay) + MAX(DataFrequency), ''' + d + '''),120))'
    FROM Dates
    ORDER BY d
    FOR XML PATH(''), TYPE 
).value('.', 'VARCHAR(MAX)') +
N'FROM #GrocessaryStore a
JOIN #Month_Report b ON a.StoreID = b.StoreID
WHERE Date_of_Day BETWEEN @FromDate AND @ToDate
GROUP BY Name;';

PRINT @SQL;
EXEC sp_executesql @SQL, @SQLParms, @FromDate=@FromDate, @ToDate=@ToDate;

GO
DROP TABLE #GrocessaryStore;
DROP TABLE #Month_Report;	
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
SQL Server Forums © 2000-2009 SQLTeam Publishing, LLC Go To Top Of Page
This page was generated in 0.11 seconds. Powered By: Snitz Forums 2000