SQL Query, FULL JOIN, производительность - PullRequest
1 голос
/ 08 июля 2011

У меня есть таблица свойств для одного человека, один и тот же человек может иметь до 18 различных свойств. Таблица выглядит так:

Personid, Propertytype, Propertyvalue, Propertyname

Я хочу выполнить SQL-запрос с FULL JOIN, чтобы получить все свойства одного человека в одну строку в наборе результатов. Я сделал такой запрос, но думаю, что он не оптимален, если вы думаете о времени отклика / производительности. В базе данных у меня более 12 миллионов человек, поэтому много датаров.

Мой 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

Какой-нибудь совет, как сделать этот запрос более эффективным?

Ответы [ 4 ]

2 голосов
/ 08 июля 2011

Попробуйте использовать PIVOT.ссылка на BOL здесь ... http://link.phillip.pe/SQLPivot.

переводит несколько строк в одном столбце в несколько столбцов в одной строке, например,

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

PIVOT в:

Person1, Left-Handed, Blue Eyes
Person2, Right-Handed, Brown Eyes
2 голосов
/ 08 июля 2011

Вы можете выбрать строки, которые вам нужны, а затем PIVOT строк в столбцы, 1 способ будет использовать оператор case в select для каждого идентификатора. Это уменьшит количество сканирований таблицы «человек» (так как сканирование таблицы будет выполнено только один раз). например:

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
1 голос
/ 08 июля 2011

Я бы попробовал, либо работать с 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 голосов
/ 08 июля 2011

Это можно сделать с помощью комбинации операций PIVOT и UNPIVOT.

;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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...