2011-07-08 15 views
1

私は一人のためのプロパティを持つテーブルを持って、同じ人が最大18の異なるプロパティを持つことができます。テーブルには、次のようになります。SQLクエリ、FULL JOIN、パフォーマンス

Personid, Propertytype, Propertyvalue, Propertyname 

私はFULLでSQLクエリを実行したいが、結果セットの1行に1人のためのすべてのプロパティを取得するために参加します。 私はこのようなクエリを実行しましたが、応答時間/パフォーマンスについて考えると最適ではないと思います。 データベースには私は1,200万人以上の人がいますので、多くのデータローです。

マイSQLクエリ:

SELECT DISTINCT (Information.PersonID), 
    f.PersonName, 
    f1.Property AS 'P1', 
    f1.PropertyValue AS 'P1Value', 
    f1.PropertyName AS 'P1Name', 
    f2.Property AS 'P2', 
    f2.PropertyValue AS 'P2Value', 
    f2.PropertyName AS 'P2Name', 
    ...... 
FROM Person f 
FULL JOIN (
    SELECT 
     PersonName, 
     Property, 
     PropertyValue, 
     PropertyName 
    FROM Person WHERE Property='P1' 
    GROUP BY PersonName, Property, PropertyValue, PropertyName 
) f1 ON f.PersonName=f1.PersonName 
FULL JOIN (
    SELECT PersonName, 
     Property, 
     PropertyValue, 
     PropertyName 
    FROM Person WHERE Property='P2' 
    GROUP BY PersonName, Property, PropertyValue, PropertyName 
) f2 ON f.PersonName=f2.PersonName 
    .... 
INNER JOIN Information ON f.PersonName = Information.Name 

何かアドバイスはどのようにより効果的に、このクエリを実行するには?

+0

テーブルにはどのようなインデックスがありますか?また、テーブル構造(フィールドとタイプ)を追加してください –

+0

何を使用していますか、SQL Server、MySQL、DB2など? – Aphillippe

+0

**両方の**テーブルのテーブル構造、PersonとInformation。 –

答えて

2

必要な行を選択し、行を列にPIVOTして、各IDのselectにcaseステートメントを使用することができます。 これは、personテーブルに対するスキャンの数を減少させるであろう(あなたは一度だけのテーブルをスキャンしなければならないよう) 例えば:。

SELECT personID,PersonName, max(p1val),max(p1name),max(p2val),max(p2name) ...etc 
FROM 
(
    SELECT Information.PersonID, 
    f.PersonName, 
    case WHEN Property ='P1' THEN PropertyValue ELSE NULL END as p1val, 
    case WHEN Property ='P2' THEN PropertyValue ELSE NULL END as p2val, 
    case WHEN Property ='P3' THEN PropertyValue ELSE NULL END as p3val, 
    ....etc 
    case WHEN Property ='P1' THEN PropertyName ELSE NULL END as p1name, 
    case WHEN Property ='P2' THEN PropertyName ELSE NULL END as p2name, 
    case WHEN Property ='P3' THEN PropertyName ELSE NULL END as p3name, 
    .....etc 
    FROM Person f 
) 
GROUP BY personID,PersonName 
+0

そこにいくつかの集約が必要な場合や、ピボットしていない場合... – ErikE

+0

良い点、こんにちは...私は訂正します –

+0

これはプロパティが重複していなければ必要なタスクを実行する最速の方法だと思われますが、しかし、このソリューションは、他のほとんどのソリューションよりも優れた処理をします – Seph

2

PIVOTを使用してみてください。ここにBOLへのリンク... http://link.phillip.pe/SQLPivot

1列の複数の行を1行の複数の列に変換します。

Person1, Left-Handed 
Person1, Blue Eyes 
Person2, Right-Handed 
Person2, Brown Eyes 

PIVOT:

Person1, Left-Handed, Blue Eyes 
Person2, Right-Handed, Brown Eyes 
+0

2列をピボットすることは可能ですか? –

1

私はPIVOT、またはこれで作業のいずれか、しようとするだろう:

SELECT 
    i.PersonID 
    , i.PersonName 
    , f1.Property AS 'P1' 
    , f1.PropertyValue AS 'P1Value' 
    , f1.PropertyName AS 'P1Name' 

    , f2.Property AS 'P2' 
    , f2.PropertyValue AS 'P2Value' 
    , f2.PropertyName AS 'P2Name' 

    ...... 
FROM 
    Information AS i 
    LEFT JOIN Person AS f1 
     ON f1.PersonID = i.PersonId 
     AND f1.Property = 'P1' 
    LEFT JOIN Person AS f2 
     ON f2.PersonID = i.PersonId 
     AND f2.Property = 'P2' 
    ...... 
+0

これは私のソリューションよりも速いです...同じ応答時間のようですね! – Carin

+0

私はOPの答えからのサブクエリが必要であると確信していません。毎回Personに直接参加するだけですか? – MatBailie

+0

あなたは私たちにテーブルのインデックスを教えていません。 –

0

これはPIVOTUNPIVOT操作の組み合わせで行うことができます。

;WITH a AS 
(
    SELECT PersonName 
     , Property [Prefix] 
     , Property [ ] 
     , PropertyValue [Value] 
     , PropertyName [Name] 
    FROM dbo.Person 
) 
, c AS 
(
    SELECT b.PersonName, RTRIM(b.Prefix + b.Suffix) Field, b.Data 
    FROM a 
    UNPIVOT (Data FOR Suffix IN ([ ], [Value], [Name])) b 
) 
SELECT d.* 
FROM c PIVOT (MIN(Data) FOR Field IN 
    (
     [P1], [P1Value], [P1Name] 
     , [P2], [P2Value], [P2Name] 
     , [P3], [P3Value], [P3Name] 
    )) d 
関連する問題