Reputation: 4339
I am trying to port some C# to TSQL because the performance is unsatisfactory. The C# makes multiple database calls.
This is for a scraper of accommodation properties. The schema is as follows:
Scrapes
ScrapeResults
Essentially the whole point of this is that the database tracks internal room prices compared to near by competitors. The fkRoomId
column on ScrapeResults
defines each room uniquely. Each time a competitor is scraped there is a new entry in the Scrapes table, and the results of the scrape is saved in ScrapeResults. Start and End dates are a 1 week period. The scrapes weekly prices for a 3 month period. The scrape happens once a week, which is the purpose of fkSessionId
which relats to a unique scraping session.
The C# code builds a report that looks like this:
I'm not quite sure if it's possible to build a SQL query for this. I've written a stored procedure that builds up a dynamic SQL string. Here was my first attempt:
select sr.ScrapeId,
sr.fkProviderId,
sr.startDate,
sr.endDate,
sr1.price,
sr2.price,
sr3.price,
sr4.price,
sr5.price,
sr6.price,
sr7.price,
sr8.price,
sr9.price,
sr10.price,
sr11.price,
sr12.price
from Scrapes sr
left join ScrapeResults sr1 on sr1.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr2 on sr2.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr3 on sr3.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr4 on sr4.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr5 on sr5.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr6 on sr6.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr7 on sr7.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr8 on sr8.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr9 on sr9.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr10 on sr10.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr11 on sr11.fkScrapeId = sr.ScrapeId
left join ScrapeResults sr12 on sr12.fkScrapeId = sr.ScrapeId
WHERE sr.fkSession = 25
and sr.startDate='2014-03-22'
and sr.fkLocationId = 1
and sr1.fkRoomId = 11
and sr2.fkRoomId = 15
and sr3.fkRoomId = 19
and sr4.fkRoomId = 23
and sr5.fkRoomId = 25
and sr6.fkRoomId = 27
and sr7.fkRoomId = 32
and sr8.fkRoomId = 39
and sr9.fkRoomId = 41
and sr10.fkRoomId = 45
and sr11.fkRoomId = 47
and sr12.fkRoomId = 50
I know I'm off the mark here but would appreciate pointers. Thanks.
Upvotes: 0
Views: 81
Reputation: 11079
You can do this simpler with the PIVOT option, pivoting on the fkRoomID column. You can do it manually with a single query but that annoys me because you have to specify the fkRoomID value in the SQL for the PIVOT statement so if the number of rooms changes you have to change the SQL, like this:
select
sc.ScrapeId,
sc.fkProviderId,
sc.startDate,
sc.endDate,
scr.fkRoomId,
scr.price
from
Scrapes sc
join ScrapeResults scr
on ( scr.fkScrapeId = sr.ScrapeId )
pivot (max(price) for fkRoomId in ([11],[15],[19],[23],[25],[27],[32],[39],[41],[45],[47],[50]))
where
sr.fkSession = 25
and sr.startDate = '2014-03-22'
and sr.fkLocationId = 1
I prefer to use this stored procedure I wrote named pivot_query . To use it you would format your query like this:
declare @mySQL varchar(MAX);
set @mySQL = '
select
sc.ScrapeId,
sc.fkProviderId,
sc.startDate,
sc.endDate,
scr.fkRoomId,
scr.price
from
Scrapes sc
join ScrapeResults scr
on ( scr.fkScrapeId = sr.ScrapeId )
where
sr.fkSession = 25
and sr.startDate = ''2014-03-22''
and sr.fkLocationId = 1
';
exec pivot_query @mySQL, 'StartDate, EndDate, fkProviderId','fkRoomId','max(price)'
That's the basic concept but if you have another reference table with the Room Names it it you could also join that table and use the Room Names to pivot on, so the columns would have the room names at the top.
There are some examples for using the pivot_query proc here.
Upvotes: 1
Reputation: 45096
You were breaking the left join by an srX.fkRoomId =
So might as well just do a join
Or in this format you actually can do a left join and not break it
The query optimizer can typically do a better job with the syntax
I see not problem with building this up in C#
select sr.ScrapeId,
sr.fkProviderId,
sr.startDate,
sr.endDate,
sr1.price,
sr2.price,
...
from Scrapes sr
join ScrapeResults sr1
on sr1.fkScrapeId = sr.ScrapeId
and sr1.fkRoomId = 11
join ScrapeResults sr2
on sr2.fkScrapeId = sr.ScrapeId
and sr2.fkRoomId = 15
....
WHERE sr.fkSession = 25
and sr.startDate='2014-03-22'
and sr.fkLocationId = 1
Upvotes: 1