Click here to monitor SSC
SQLServerCentral is supported by Red Gate Software Ltd.
 
Log in  ::  Register  ::  Not logged in
 
 
 
        
Home       Members    Calendar    Who's On


Add to briefcase 12»»

Turning raw data into a grid layout Expand / Collapse
Author
Message
Posted Tuesday, January 1, 2013 8:24 PM
SSC Journeyman

SSC JourneymanSSC JourneymanSSC JourneymanSSC JourneymanSSC JourneymanSSC JourneymanSSC JourneymanSSC Journeyman

Group: General Forum Members
Last Login: Sunday, April 27, 2014 8:38 PM
Points: 90, Visits: 420
Hi all,

not sure how best to explain what I'm trying to do so will try to break it down as easy as i can.

I have a table which stores all prices for companies daily trading. Companies ABC & XYZ have information available for what was the high & low values for a DateID.



CREATE TABLE [dbo].[TestGrid]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[CompanyName] [varchar](200) NOT NULL,
[DateID] [int] NOT NULL,
[High] [float] NOT NULL,
[Low] [float] NOT NULL
)

INSERT INTO [dbo].[TestGrid] (CompanyName,DateID,High,Low)
VALUES ('ABC',20121201,0.5,1.0)

INSERT INTO [dbo].[TestGrid] (CompanyName,DateID,High,Low)
VALUES ('ABC',20121202,0.6,1.5)

INSERT INTO [dbo].[TestGrid] (CompanyName,DateID,High,Low)
VALUES ('ABC',20121203,1.0,1.6)


INSERT INTO [dbo].[TestGrid] (CompanyName,DateID,High,Low)
VALUES ('XYZ',20121201,0.5,0.4)

INSERT INTO [dbo].[TestGrid] (CompanyName,DateID,High,Low)
VALUES ('XYZ',20121202,0.6,0.5)

INSERT INTO [dbo].[TestGrid] (CompanyName,DateID,High,Low)
VALUES ('XYZ',20121203,1.0,0.6)



ID CompanyName DateID High Low
----------- ----------------------------------------------------------
1 ABC 20121201 0.5 0.1
2 ABC 20121202 0.6 0.5
3 ABC 20121203 1 0.6
4 XYZ 20121201 0.5 0.4
5 XYZ 20121202 0.6 0.5
6 XYZ 20121203 1 0.6




What I'm trying to do is turn the DateID into columns and then as a additional change those columns represent the actual day of the Date ID How would i know 20121201 is equal to say Monday and 02 is Tuesday?


END RESULT:


NAME TYPE MONDAY TUESDAY WEDNESDAY
ABC HIGH 0.5 0.6 1
ABC LOW 0.1 1.5 0.6


I'm not sure if cross join / pivot or something else should be used so if i could get a hand would be great
Post #1401641
Posted Tuesday, January 1, 2013 9:03 PM


Hall of Fame

Hall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of Fame

Group: General Forum Members
Last Login: Yesterday @ 3:25 AM
Points: 3,417, Visits: 5,328
You might try this:

SELECT CompanyName, Type
,Sunday=MAX(CASE WHEN weekday = 1 THEN Val END)
,Monday=MAX(CASE WHEN weekday = 2 THEN Val END)
,Tuesday=MAX(CASE WHEN weekday = 3 THEN Val END)
,Wednesday=MAX(CASE WHEN weekday = 4 THEN Val END)
,Thursday=MAX(CASE WHEN weekday = 5 THEN Val END)
,Friday=MAX(CASE WHEN weekday = 6 THEN Val END)
,Saturday=MAX(CASE WHEN weekday = 7 THEN Val END)
FROM dbo.TestGrid
CROSS APPLY (
VALUES(High, 'High', DATEPART(dw, CAST(DateID AS CHAR(8))))
,(Low, 'Low', DATEPART(dw, CAST(DateID AS CHAR(8))))) a(Val, Type, weekday)
GROUP BY CompanyName, Type


And you will also want to Google "SQL DATEFIRST" to see how this query is sensitive to that setting.

You can look at the first link in my signature to see how the CROSS APPLY VALUES works (like an UNPIVOT but usually faster).

I won't ask (but should) why (before someone else does) you're storing a date as an INT instead of a DATETIME.



My mantra: No loops! No CURSORs! No RBAR! Hoo-uh!

My thought question: Have you ever been told that your query runs too fast?

My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.


Need to UNPIVOT? Why not CROSS APPLY VALUES instead?
Since random numbers are too important to be left to chance, let's generate some!
Learn to understand recursive CTEs by example.
Splitting strings based on patterns can be fast!
Post #1401643
Posted Wednesday, January 2, 2013 7:40 AM


SSC-Insane

SSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-Insane

Group: General Forum Members
Last Login: Today @ 2:31 PM
Points: 20,679, Visits: 32,261
dwain.c (1/1/2013)
You might try this:

SELECT CompanyName, Type
,Sunday=MAX(CASE WHEN weekday = 1 THEN Val END)
,Monday=MAX(CASE WHEN weekday = 2 THEN Val END)
,Tuesday=MAX(CASE WHEN weekday = 3 THEN Val END)
,Wednesday=MAX(CASE WHEN weekday = 4 THEN Val END)
,Thursday=MAX(CASE WHEN weekday = 5 THEN Val END)
,Friday=MAX(CASE WHEN weekday = 6 THEN Val END)
,Saturday=MAX(CASE WHEN weekday = 7 THEN Val END)
FROM dbo.TestGrid
CROSS APPLY (
VALUES(High, 'High', DATEPART(dw, CAST(DateID AS CHAR(8))))
,(Low, 'Low', DATEPART(dw, CAST(DateID AS CHAR(8))))) a(Val, Type, weekday)
GROUP BY CompanyName, Type


And you will also want to Google "SQL DATEFIRST" to see how this query is sensitive to that setting.

You can look at the first link in my signature to see how the CROSS APPLY VALUES works (like an UNPIVOT but usually faster).

I won't ask (but should) why (before someone else does) you're storing a date as an INT instead of a DATETIME.


Try this, it shouldn't be sensitive to the DATEFIRST setting. It relies on 1900-01-01 being a Monday.


SELECT
CompanyName
,Type
,Sunday = MAX(CASE WHEN weekday = datename(dw, dateadd(dd, 1 - 2, '19000101')) THEN Val END)
,Monday = MAX(CASE WHEN weekday = datename(dw, dateadd(dd, 2 - 2, '19000101')) THEN Val END)
,Tuesday = MAX(CASE WHEN weekday = datename(dw, dateadd(dd, 3 - 2, '19000101')) THEN Val END)
,Wednesday = MAX(CASE WHEN weekday = datename(dw, dateadd(dd, 4 - 2, '19000101')) THEN Val END)
,Thursday = MAX(CASE WHEN weekday = datename(dw, dateadd(dd, 5 - 2, '19000101')) THEN Val END)
,Friday = MAX(CASE WHEN weekday = datename(dw, dateadd(dd, 6 - 2, '19000101')) THEN Val END)
,Saturday = MAX(CASE WHEN weekday = datename(dw, dateadd(dd, 7 - 2, '19000101')) THEN Val END)
FROM dbo.TestGrid
CROSS APPLY (
VALUES(High, 'High', DATENAME(dw, CAST(DateID AS CHAR(8))))
,(Low, 'Low', DATENAME(dw, CAST(DateID AS CHAR(8))))) a(Val, Type, weekday)
GROUP BY CompanyName, Type;





Lynn Pettis

For better assistance in answering your questions, click here
For tips to get better help with Performance Problems, click here
For Running Totals and its variations, click here or when working with partitioned tables
For more about Tally Tables, click here
For more about Cross Tabs and Pivots, click here and here
Managing Transaction Logs

SQL Musings from the Desert Fountain Valley SQL (My Mirror Blog)
Post #1401844
Posted Wednesday, January 2, 2013 2:30 PM
SSC Journeyman

SSC JourneymanSSC JourneymanSSC JourneymanSSC JourneymanSSC JourneymanSSC JourneymanSSC JourneymanSSC Journeyman

Group: General Forum Members
Last Login: Sunday, April 27, 2014 8:38 PM
Points: 90, Visits: 420
Thanks guys, i've tried both and both get the same results as i expected. I thought i had use cross apply just wasn't too sure how to use it to get what i expected.

To answer the question about why is DateID int and not datetime its an old table and data already in there. I assume its for an indexing/performance benefit and everything is based on dateid for searching? does that sound about right?

Post #1402089
Posted Wednesday, January 2, 2013 5:36 PM


Hall of Fame

Hall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of Fame

Group: General Forum Members
Last Login: Yesterday @ 3:25 AM
Points: 3,417, Visits: 5,328
Tava (1/2/2013)

To answer the question about why is DateID int and not datetime its an old table and data already in there. I assume its for an indexing/performance benefit and everything is based on dateid for searching? does that sound about right?



It is not the first time I've heard of someone being stuck with a legacy design. If you're in SQL 2008 and designing anew, using DATE datatype would provide the same indexing/performance benefit as what you've done. I actually doubt there would be a difference had the field been created as a DATETIME (just perhaps a little more application housekeeping to ensure that no time part is stored with it).

Lynn - Nice way to eliminate the dependency on DATEFIRST.



My mantra: No loops! No CURSORs! No RBAR! Hoo-uh!

My thought question: Have you ever been told that your query runs too fast?

My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.


Need to UNPIVOT? Why not CROSS APPLY VALUES instead?
Since random numbers are too important to be left to chance, let's generate some!
Learn to understand recursive CTEs by example.
Splitting strings based on patterns can be fast!
Post #1402125
Posted Wednesday, January 2, 2013 6:02 PM


SSC-Insane

SSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-Insane

Group: General Forum Members
Last Login: Today @ 2:31 PM
Points: 20,679, Visits: 32,261
dwain.c (1/2/2013)
Tava (1/2/2013)

To answer the question about why is DateID int and not datetime its an old table and data already in there. I assume its for an indexing/performance benefit and everything is based on dateid for searching? does that sound about right?



It is not the first time I've heard of someone being stuck with a legacy design. If you're in SQL 2008 and designing anew, using DATE datatype would provide the same indexing/performance benefit as what you've done. I actually doubt there would be a difference had the field been created as a DATETIME (just perhaps a little more application housekeeping to ensure that no time part is stored with it).

Lynn - Nice way to eliminate the dependency on DATEFIRST.


I don't think it works the way I expected it to, looks like it is missing part of the code due to a poor copy and past. I'll have to look at later when I get back to the apartment.



Lynn Pettis

For better assistance in answering your questions, click here
For tips to get better help with Performance Problems, click here
For Running Totals and its variations, click here or when working with partitioned tables
For more about Tally Tables, click here
For more about Cross Tabs and Pivots, click here and here
Managing Transaction Logs

SQL Musings from the Desert Fountain Valley SQL (My Mirror Blog)
Post #1402130
Posted Wednesday, January 2, 2013 6:16 PM


Hall of Fame

Hall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of Fame

Group: General Forum Members
Last Login: Yesterday @ 3:25 AM
Points: 3,417, Visits: 5,328
Lynn Pettis (1/2/2013)
dwain.c (1/2/2013)
Tava (1/2/2013)

To answer the question about why is DateID int and not datetime its an old table and data already in there. I assume its for an indexing/performance benefit and everything is based on dateid for searching? does that sound about right?



It is not the first time I've heard of someone being stuck with a legacy design. If you're in SQL 2008 and designing anew, using DATE datatype would provide the same indexing/performance benefit as what you've done. I actually doubt there would be a difference had the field been created as a DATETIME (just perhaps a little more application housekeeping to ensure that no time part is stored with it).

Lynn - Nice way to eliminate the dependency on DATEFIRST.


I don't think it works the way I expected it to, looks like it is missing part of the code due to a poor copy and past. I'll have to look at later when I get back to the apartment.


Hehe. I didn't try to run it but understood what you were trying to do. I think you meant this (in the CASE statements):

SELECT datename(dw, dateadd(day, 1 - 2, '19000101'))  -- for Sunday





My mantra: No loops! No CURSORs! No RBAR! Hoo-uh!

My thought question: Have you ever been told that your query runs too fast?

My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.


Need to UNPIVOT? Why not CROSS APPLY VALUES instead?
Since random numbers are too important to be left to chance, let's generate some!
Learn to understand recursive CTEs by example.
Splitting strings based on patterns can be fast!
Post #1402133
Posted Wednesday, January 2, 2013 7:05 PM


SSC-Insane

SSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-Insane

Group: General Forum Members
Last Login: Today @ 2:31 PM
Points: 20,679, Visits: 32,261
dwain.c (1/2/2013)
Lynn Pettis (1/2/2013)
dwain.c (1/2/2013)
Tava (1/2/2013)

To answer the question about why is DateID int and not datetime its an old table and data already in there. I assume its for an indexing/performance benefit and everything is based on dateid for searching? does that sound about right?



It is not the first time I've heard of someone being stuck with a legacy design. If you're in SQL 2008 and designing anew, using DATE datatype would provide the same indexing/performance benefit as what you've done. I actually doubt there would be a difference had the field been created as a DATETIME (just perhaps a little more application housekeeping to ensure that no time part is stored with it).

Lynn - Nice way to eliminate the dependency on DATEFIRST.


I don't think it works the way I expected it to, looks like it is missing part of the code due to a poor copy and past. I'll have to look at later when I get back to the apartment.


Hehe. I didn't try to run it but understood what you were trying to do. I think you meant this (in the CASE statements):

SELECT datename(dw, dateadd(day, 1 - 2, '19000101'))  -- for Sunday




Should also take care of language differences.



Lynn Pettis

For better assistance in answering your questions, click here
For tips to get better help with Performance Problems, click here
For Running Totals and its variations, click here or when working with partitioned tables
For more about Tally Tables, click here
For more about Cross Tabs and Pivots, click here and here
Managing Transaction Logs

SQL Musings from the Desert Fountain Valley SQL (My Mirror Blog)
Post #1402144
Posted Thursday, January 3, 2013 1:02 AM


SSCrazy

SSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazy

Group: General Forum Members
Last Login: Tuesday, August 19, 2014 12:26 AM
Points: 2,840, Visits: 3,963
i tried it with PIVOT but its more resource intensive (as compared to other provided solution ) . can we avoid UNION here


SELECT CompanyName, 'Low' as Type,
[Sunday], [Monday], [tuesday], [wednesday], [thursday],[Friday],[Saturday]
FROM
(
select
CompanyName,
Low,
CASE
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 1 THEN 'Sunday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 2 THEN 'Monday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 3 THEN 'tuesday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 4 THEN 'wednesday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 5 THEN 'thursday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 6 THEN 'Friday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 7 THEN 'Saturday'
END as WeekDays
from [TestGrid]
) AS SourceTable
PIVOT
(
SUM(Low)
FOR WeekDays IN ([Sunday], [Monday], [tuesday], [wednesday], [thursday],[Friday],[Saturday])
) AS PivotTable
UNION
SELECT CompanyName, 'High' as Type,
[Sunday], [Monday], [tuesday], [wednesday], [thursday],[Friday],[Saturday]
FROM
(
select
CompanyName,
High,
CASE
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 1 THEN 'Sunday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 2 THEN 'Monday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 3 THEN 'tuesday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 4 THEN 'wednesday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 5 THEN 'thursday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 6 THEN 'Friday'
WHEN DATEPART(dw, CAST(DateID AS CHAR(8))) = 7 THEN 'Saturday'
END as WeekDays
from [TestGrid]
) AS SourceTable
PIVOT
(
SUM(High)
FOR WeekDays IN ([Sunday], [Monday], [tuesday], [wednesday], [thursday],[Friday],[Saturday])
) AS PivotTable



-------Bhuvnesh----------
I work only to learn Sql Server...though my company pays me for getting their stuff done
Post #1402215
Posted Friday, January 4, 2013 3:19 AM


SSCrazy

SSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazy

Group: General Forum Members
Last Login: Tuesday, August 19, 2014 12:26 AM
Points: 2,840, Visits: 3,963
dwain.c (1/1/2013)

CROSS APPLY (
VALUES(High, 'High', DATEPART(dw, CAST(DateID AS CHAR(8))))
,(Low, 'Low', DATEPART(dw, CAST(DateID AS CHAR(8))))) a(Val, Type, weekday)
GROUP BY CompanyName, Type

dwain , can you please explain above sql code , i am finding it hard to understand


-------Bhuvnesh----------
I work only to learn Sql Server...though my company pays me for getting their stuff done
Post #1402766
« Prev Topic | Next Topic »

Add to briefcase 12»»

Permissions Expand / Collapse