查询有很多连接 - 将C#移植到SQL Server

时间:2014-07-12 06:42:00

标签: sql sql-server performance tsql

我正在尝试将一些C#移植到TSQL,因为性能不令人满意。 C#进行多次数据库调用。

这是适用于住宿物业的刮刀。架构如下:

擦伤

  • ScrapeId
  • fkProviderId
  • fkLocation
  • fkSessionId
  • 开始
  • 结束

ScrapeResults

  • fkScrapeId
  • fkRoomId

基本上,这一点的重点是数据库跟踪内部房价与竞争对手相比较。 fkRoomId上的ScrapeResults列唯一地定义了每个房间。每次刮擦竞争对手时,Scrapes表中都会有一个新条目,并且Scrape的结果会保存在ScrapeResults中。开始和结束日期为1周。每周的价格为3个月。刮伤每周发生一次,这是fkSessionId与独特刮擦会话相关的目的。

C#代码构建一个如下所示的报告:

  • 开始日期
  • 结束日期
  • 我们的房间类型
  • 竞争室1
  • 竞争对手室2
  • ...
  • 竞争对手n

我不太确定是否可以为此构建SQL查询。我编写了一个存储过程来构建动态SQL字符串。这是我的第一次尝试:

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

我知道我不在这里,但会很感激指针。感谢。

2 个答案:

答案 0 :(得分:1)

您正在通过srX.fkRoomId =
打破左连接 所以不妨只做一个加入 或者以这种格式,你实际上可以做一个左连接而不是打破它 查询优化器通常可以使用语法
做得更好 我认为在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 

答案 1 :(得分:1)

使用PIVOT选项,在fkRoomID列上进行旋转,可以更简单地完成此操作。您可以使用单个查询手动执行此操作,但这会让我感到烦恼,因为您必须在SQL中为PIVOT语句指定fkRoomID值,因此如果更改了房间数,则必须更改SQL,如下所示:

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

我更喜欢使用我写的名为pivot_query的存储过程。要使用它,您可以格式化您的查询:

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)'

这是基本概念,但如果您有另一个带有房间名称的参考表,您也可以加入该表并使用房间名称进行转动,因此列的房间名称将位于顶部

有一些使用pivot_query proc here的例子。