如何有效地查询多个主记录及其一对多记录

时间:2011-06-19 00:23:21

标签: sql-server performance coldfusion

考虑以下结构DB结构。目前的工作语言是Coldfusion和MSSQL。

Tables
Hotels: - Columns - hotelid, name, company, address, state, city, zip
Media: - Columns - mediaid, label, url
HotelsXMedia: - Columns - xid, hotelid, mediaid

基本上我们有一个包含酒店的表和一个包含图像的表和一个用于处理多对多关系的交叉表。期望的输出是单个数组(或查询),每个项目都包含hotels表中的所有列以及主行中的媒体表的所有行,因此可以将其传递给主题函数,例如。

当前方法是查询酒店,转换为数组,从结果集中提取hotelids。查询基于hotelid的媒体。将结果媒体查询转换为索引为hotelid的结构。然后遍历酒店阵列并将其媒体数据分配到酒店阵列。然后将酒店阵列传递到任何需要去的地方。

有更有效的方法吗?有没有办法在不进行两次SQL查询和所有结果折叠和循环的情况下执行此操作。应用程序中几乎每个模块都使用媒体表来存储它的图像,因此对于页面上的几乎每个组件,我们都必须执行这种组合,这看起来非常麻烦。有没有更好的方法?此外,虽然它可能只提供一点点好处来增强这一对多的查询组合,因为它在90%的组件中是必要的,增强的好处会扩散到所有组件,从而产生不错的收益。

如果结果查询中的列是已连接的MEDIA网址的分隔列表,我认为这是一个可行的解决方案。但不幸的是在MSSQL中我们没有group_concat()。如果这个方法已经完成,那么有一种简单的方法可以获取多个列,例如我想要获取媒体:url和media:label?有没有办法确保如果媒体表中的记录有一个url但缺少一个标签,那么空值或空值仍会得到分隔符,从而导致2个列表不对齐。如果我走这条路线,我必须为XML路径做多个才能到达那里吗?任何指导都将不胜感激。

4 个答案:

答案 0 :(得分:1)

答案 1 :(得分:0)

当我遇到这个问题时,我最终做了一个大查询(select * from hotelsxmedia join hotels on ... join media on ...),它返回的行数与交叉表(HotelsXMedia)的行数一样多。请务必order by hotelid。然后,当您遍历查询结果时,您可以为每个新的hotelid采取一个操作(例如,附加到数组),并为重复相同hotelid的行执行不同的操作(例如,向其添加新媒体)。

答案 2 :(得分:0)

正如@krubo建议的那样,我会做一个大型查询,然后使用group =“hotelid”属性进行cfoutput,并在其中创建数组和结构。

答案 3 :(得分:0)

您可以在hotelid排序的一个查询中执行此操作,并使用分组嵌套的CFOUTPUT构建数据结构。

<cfquery name="myHotels" datasource="HotelStuff" >
  SELECT H.*, M.*
  FROM Hotels H
      JOIN HotelsXMedia HXM ON H.hotelid = HXM.hotelid
      JOIN Media M ON M.mediaid = HXM.mediaid
  ORDER BY H.hotelid
</cfquery>

CFOUTPUT的group =“”属性导致循环按照hotelid字段值的变化进行分组。

<cfoutput query="myHotels" group="hotelid">
  <cfset hotels = {
     hotelid = myHotels.hotelid,
     name = myHotels.name,
     company = myHotels.company,
     address = myHotels.address,
     state = myHotels.state,
     city = myHotels.city,
     zip = myHotels.zip,
     media = arrayNew(1)
  } />

  <cfoutput>
     <cfset thisMedia = { label = myHotels.label, url = myHotels.url } />
     <cfset arrayAppend(hotels.media, thisMedia) />
  </cfoutput>
</cfoutput>

你可以通过Hotels.name订购,有时可以侥幸逃脱;你需要确保没有两家酒店拥有完全相同的名称,否则它们将被折叠成一个组。使用基于主键列的组通常更安全。