2011-06-19 6 views
2

次の構造DB構造を考慮してください。現在の作業言語はColdfusionとMSSQLです。複数プライマリレコードとその1対多レコードを効率的に照会する方法

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

基本的に私たちはホテルや画像やクロス表は、多くの関係に多くを処理するために含まれているテーブルとテーブルを持っています。必要な出力は単一の配列(またはクエリ)であり、各項目はhotelsテーブルのすべての列と、その行のすべての行をプライマリ行内に持つので、theming関数に渡すことができます。例えば。

現在の方法は、ホテルを照会し、配列に変換し、結果セットからホテルIDを抽出することです。 hotelidに基づいてメディアを照会します。結果のメディアクエリをインデックスがhotelidである構造体に変換します。その後、ホテルの配列をループし、その配列にメディアデータを割り当てます。その後、ホテルの配列をどこにでも移動する必要がある場所に渡します。

これを行うより効率的な方法はありますか? 2つのSQLクエリとその結果の折りたたみとループのすべてを行わずにこれを行う方法はありますか?アプリケーションのほぼすべてのモジュールがメディアテーブルを利用して画像を保存しているため、ページ上のほぼすべてのコンポーネントに対してこのような組み合わせを実行する必要があり、かなり面倒です。良い方法はありますか?さらに、コンポーネントの90%で必要となるため、この1対複数のクエリの組み合わせを強化するためにわずかなメリットしか得られないかもしれませんが、エンハンスメントのメリットはすべてに広がり、結果としてまともな利益をもたらします。

結果クエリの列が結合されたMEDIA URLの区切られたリストであった場合、それを実行可能なソリューションと考えています。しかし残念ながら、MSSQLではgroup_concat()がありません。このメソッドが完了していれば、複数の列を取得する簡単な方法があります。たとえば、メディアを取得する場合は:urlとmedia:ラベルですか?メディアテーブル内のレコードにURLがあり、ラベルがないために2つのリストが整列しない場合、空の値またはヌル値にデリミタが残っていることを確認する方法はありますか?私がこのルートに行ったら、そこに着くためにXMLパスのために複数の作業をする必要がありますか?どんな指針も大変ありがとうございます。

答えて

1
+0

私はクロス・アプライをしませんでしたが、FOR XML PATH( '')は、必要なものすべてが1または2列であれば十分に機能しました。それよりもはるかに大きいので、2つのクエリに分割してクライアント側にグループ化するほうが簡単です。データをより洗練されたものにする。 – Nucleon

0

私はこの問題に直面したとき、私はクロス表(HotelsXMedia)の行のように多くの行を返す一つの大きなクエリ(select * from hotelsxmedia join hotels on ... join media on ...)を、作り終わりました。ちょうどorder by hotelidにしてください。次に、クエリー結果をループすると、新しいhotelidごとに1つのアクション(配列に追加するなど)と、同じhotelidを繰り返す行に対して異なるアクション(たとえば、新しいメディアを追加)を取ることができます。

0

@kruboが示唆するように、私は1つの大きなクエリを実行し、次にgroup = "hotelid"属性を使用してcfoutputを実行し、その中に配列と構造体を作成します。

0

ホテルIDで注文したすべてのクエリでこれをすべて実行し、グループ化されたネストされた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で注文することもできます。 2つのホテルの名前がまったく同じではないか、1つのグループにまとめられることを確認する必要があります。主キー列に基づいてグループを使用する方が一般的に安全です。

関連する問題