1

LEFTJOINをテーブル/マトリックスに変換するための良い解決策を知りたいです。

たとえば、次のスキーマがあるとします。

オブジェクト
   id(整数)
   名前(文字列)

属性
   id(整数)
   object_id(整数)
   名前(文字列)
   値(文字列)

そしてこれらの値:

1、ボール
2、ボックス

1,1、カラー、レッド
2,1、形状、球
3,1、素材、ゴム
4,2、カラー、ブラウン
5,2、形、立方体

これを取得したい:

object_id | object_name | 色| 形| 材料

1 | ボール| 赤| 球| ゴム
2 | ボックス| ブラウン| キューブ| ヌル

理想的には、これは各オブジェクトの属性の数が不明であり、ストアドプロシージャを使用しないMySQLの場合です。

4

4 に答える 4

2

RDBMSの目的は、すでに持っているものを保存して提示することです。列を動的に作成することは意図されていませんでした。

これは、データを提示するクライアントで処理する必要があるケースです。

RDBMSの使用方法を無視しても、これを行う簡単な方法はまだ見つかりません。特に、列リストを動的にしたい場合はそうではありません。動的SQLクエリを作成して実行することはできますが、標準のSQLクエリを記述してその結果を取得する方法はありません(常にすべての列を明示的に指定し、を使用してバーを指定する*ため、この場合はこれを有利に使用できません) 。)

于 2009-07-20T12:40:30.247 に答える
1

で動的クエリを使用せずにそれを行うことはできませんSQL

SQL扱うセットはすべて、固定名の固定数の列を想定しています。

そうでなければ、それは多くのことにつながるでしょうSQL

たとえば、要求しているクエリで作成されたビューを想像してみてください(可能であれば)。

SELECT  object_id, colour
FROM    myquery

このビューがコンパイルされるかどうかは、クエリの結果に依存します。これにより、単なる空の結果セット(処理が簡単)ではなく、ランタイムエラー(処理が困難)が発生します。

あなたは基本的にここで結果の提示について話している、そしてこれらのことは通常クライアント側で行われる。

属性のすべての可能な名前を含むテーブルがある場合はattribute_names、次のようにすることができます。

SELECT  o.name, an.name, a.value
FROM    objects o
CROSS JOIN
        attribute_names an
LEFT JOIN
        attributes a
ON      a.object = o.id
        AND a.name = an.name

、対応する値を持つすべての可能なobject_id / attribute_nameペアが含まれ、クライアント側でそれを使用して、マトリックスをより簡単に埋めることができます。

于 2009-07-20T12:38:59.997 に答える
0

うーん、これは、これを実現するための2つの論理的な手順が欠落している可能性があります。

必要なのは、AttributeTypesテーブルとAttributeValuesテーブルです。

objects
   id (integer)
   name (string)

attribute_types
   id (integer)
   name (string)
   description (string)
   enabled (bit)

attribute_values
   id (integer)
   attribute_type_id (integer)
   value (string)
   enabled (bit)

attributes
   id (integer)
   object_id (integer)
   attribute_type_id (integer)
   attribute_value_id (integer)

したがって、オブジェクトは属性を持つことができます。これらの属性は、attribute_type_idおよびattribute_value_idによって指定されます。

これにより、複数の属性を持つオブジェクトを作成できます。

例えば

object 
-> 1, ball

attribute_types
-> 10, Colour, null, enabled
-> 20, Shape, null, enabled
-> 30, Material, null, enabled

attribute_values 
-> 100, 10, blue, enabled
-> 200, 10, red, enabled
-> 300, 10, green, enabled

-> 400, 20, round, enabled
-> 500, 20, square, enabled
-> 600, 20, triangle, enabled

したがって、属性は次のようになります。

attributes
-> 1000, 1, 10, 100 // this item has a color and it is blue
-> 1001, 1, 20, 400 // this item has a shape and it is round
-> 1002, 1, 10, 200 // this item has a color and it is red

そのため、オブジェクトは、異なるテーブルで値を指定する複数の属性を持つことができます。ここで重要な質問は、これをどのように照会しますか?SQLの強度によっては、クエリを複数の部分に分割する必要がある場合があります。

@attribute_type_id = select Id from attribute_types where name = 'Color' // 10

select * from objects 
inner join attributes on objects.id = attributes.object_id
inner join attribute_values on objects.attribute_value_id = attribute_values.id
where attribute_type_id = @attribute_type_id
and attribute_values.value= 'blue'

そして、そこに、Colorのattribute_typeとblueのattribute_valueを持つすべてのオブジェクトを戻す必要があります。

My Sqlはそれほど強力ではありませんが、一度に複数の属性を検索する場合は、複数の句を実行できるはずです。私の考えでは、属性テーブルのattribute_type_idはattribute_typeテーブルに結合されていませんが、1ヒットでクエリを実行しやすくすることができます。パフォーマンスの面では、結合する必要がないため、クエリが高速化されます。テーブルですが、すべてがどれだけ大きくなるかによっては、違いは無視できるかもしれません。

注:私は通常、mysqlではなくmsssqlを使用しているため、データベースの種類が一致しない場合はそれが理由です。

于 2011-03-26T08:11:55.537 に答える
0

これにより、結果テーブルがマージされたと呼ばれると仮定して問題が解決されますが、私が言っているスキーマの方が優れていました。

insert into merged (object_id, object_name) select id, name from objects;
update merged m inner join attributes a on a.object_id = m.object_id and a.name = 'colour' set m.colour = a.value;
update merged m inner join attributes a on a.object_id = m.object_id and a.name = 'material' set m.material = a.value;
update merged m inner join attributes a on a.object_id = m.object_id and a.name = 'shape' set m.shape = a.value;
于 2009-07-20T12:46:14.007 に答える