0

十分に単純なはずですが、それは私にいくつかの問題を引き起こしています。

次のようなデータセットがあります。

User
  UserID
  Name
  Age

UserPropertyValues
  UserID
  PropertyCodeValueID

PropertyCodes
  PropertyCodeID
  PropertyCodeName

PropertyCodeValues
  PropertyCodeValueID
  PropertyCodeID
  PropertValue

ここで、テーブルに次のデータが含まれていると仮定します。

1  John  25
2  Sarah  34

1  2
1  3
2  1
2  3

1  FavColour
2  CarMake
3  PhoneType

1  1  Blue
2  1  Yellow
3  2  Ford
4  3  Mobile
5  3  Landline

これから、ユーザーの詳細と、プロパティコード1および2のプロパティ値を次のように返すビューを作成しようとしています。

John 25 Yellow Ford
Sarah 34 Blue Ford

私がこれまでに試したクエリは、データの繰り返し行を返す傾向があります。

John 25 Yellow
John 25 Ford
Sarah 34 Blue
Sarah 34 Ford

どんな助けでもありがたいです、事前にすべてに感謝します。

4

3 に答える 3

2

入力データ:

DECLARE @User TABLE (UserID INT, Name VARCHAR(10), Age INT)
INSERT INTO @User
SELECT 1,  'John',  25 UNION
SELECT 2,  'Sarah',  34
DECLARE @UserPropertyValues TABLE(UserID INT, PropertyCodeValueID INT)
INSERT INTO @UserPropertyValues
SELECT 1, 2 UNION
SELECT 1, 3 UNION
SELECT 2, 1 UNION
SELECT 2,  3
DECLARE @PropertyCodes 
  TABLE (PropertyCodeID INT, PropertyCodeName VARCHAR(10))
INSERT INTO @PropertyCodes
SELECT 1,  'FavColour' UNION
SELECT 2,  'CarMake' UNION
SELECT 3,  'PhoneType'
DECLARE @PropertyCodeValues TABLE (PropertyCodeValueID INT, 
  PropertyCodeID INT, PropertValue VARCHAR(10))
INSERT INTO @PropertyCodeValues
SELECT 1,  1,  'Blue' UNION
SELECT 2,  1,  'Yellow' UNION
SELECT 3,  2,  'Ford' UNION
SELECT 4,  3,  'Mobile' UNION
SELECT 5,  3,  'Landline'

結果として必要なのが2つのプロパティだけであり、各ユーザーがそれらのプロパティを持っている場合は、次のことを試してください。

SELECT U.Name, U.Age, PCVFC.PropertValue, PCVCM.PropertValue 
FROM @User U
INNER JOIN @UserPropertyValues UPVFC ON U.UserID = UPVFC.UserID 
INNER JOIN @PropertyCodeValues PCVFC 
  ON UPVFC.PropertyCodeValueID = PCVFC.PropertyCodeValueID 
    AND PCVFC.PropertyCodeID = 1
INNER JOIN @UserPropertyValues UPVCM ON U.UserID = UPVCM.UserID 
INNER JOIN @PropertyCodeValues PCVCM 
  ON UPVCM.PropertyCodeValueID = PCVCM.PropertyCodeValueID 
    AND PCVCM.PropertyCodeID = 2

[編集] しかし、可能なNULL値を処理するには、これをより適切に使用します。

SELECT U.Name, U.Age, FC.PropertValue, CM.PropertValue 
FROM @User U
LEFT JOIN (
  SELECT UserID, PropertValue FROM @UserPropertyValues  UPV
    INNER JOIN @PropertyCodeValues PCV 
      ON UPV.PropertyCodeValueID = PCV.PropertyCodeValueID 
        AND PCV.PropertyCodeID = 1
) FC ON U.UserID = FC.UserID
LEFT JOIN (
  SELECT UserID, PropertValue FROM @UserPropertyValues  UPV
    INNER JOIN @PropertyCodeValues PCV 
      ON UPV.PropertyCodeValueID = PCV.PropertyCodeValueID 
        AND PCV.PropertyCodeID = 2
) CM ON U.UserID = CM.UserID
于 2009-02-23T12:11:26.967 に答える
1

本当に必要なのは、このタイプのデータベース設計を人間的にできるだけ早く放棄することです。それは決して効果的でも効率的でもありません。3種類の値を取得するには、テーブルに3回結合する必要があります。30または40の異なるタイプの情報を取得したら、そのテーブルに何度も結合する必要があります(そして、その時点で結合を残します)。さらに、情報が必要なときはいつでも、このテーブルに参加する必要があります。これは、データベースに大きなロックの問題を引き起こしていると思います。私が使用しているデータベースの1つを最初に設計した人がこれを行い、会社が1つか2つの顧客から業界最大の顧客に成長したときに大きなパフォーマンスの問題を引き起こしました。

プロパティが、1人あたり1つの実際のレコードしかない可能性が高いプロパティである場合は、それらをユーザーテーブルに配置します。複数のレコードがある場合は、情報の種類ごとに個別のテーブルを作成します(1つはホーン用、1つは電子メール用、もう1つは車種用など)。最終的に収集する情報は通常、単純な値よりも多く、情報の種類ごとに異なり、別々のテーブルにある必要があります。次に、1つの値(たとえば、電話番号を表示するが電子メールは表示しない)のみを表示する必要がある場合は、そのテーブルに参加するだけで、電話番号ではなく電子メールにアクセスしようとする人々に干渉することはありません。また、黄色のフォードまたは白いホンダを使用している場合は、デザインの2つのプロパティレコードではなく、自動テーブルの1つのレコードにのみ保存されます。

于 2009-02-23T18:21:19.527 に答える
0
SELECT 
  u.[Name],
  u.Age,
  pcv1.PropertValue,
  pcv2.PropertValue
FROM 
  Users  u
  LEFT JOIN 
  ( UserPropertyValues upv1 
    JOIN PropertyCodeValues pcv1 ON 
    upv1.PropertyCodeValueID = pcv1.PropertyCodeValueID 
    AND pcv1.PropertyCodeID = 1
  )
  ON upv1.UserID = u.UserID
  LEFT JOIN (
    UserPropertyValues upv2 
    JOIN PropertyCodeValues pcv2 ON 
    upv2.PropertyCodeValueID = pcv2.PropertyCodeValueID 
    AND pcv2.PropertyCodeID = 2
  )
  ON upv2.UserID = u.UserID

編集:ユーザーの名前をusersに変更しました

Edit2:nullを許可します(値を入力しません)

于 2009-02-23T13:49:10.740 に答える