Оптимизация запроса SQL, который использует несколько вложенных элементов выбора для отображения столбцов - PullRequest
0 голосов
/ 05 июня 2018

Итак, у меня есть следующая схема:

enter image description here

И я пытаюсь получить данные в следующем формате:

 ________________________________________
| Id | Property1 | Property2 | Property3 |
_________________________________________
| 123| Value1     | Value2     | Value3  |
 ________________________________________

Итак, способ составления SQL-запроса выглядит следующим образом:

SELECT
Id
,(SELECT pv.Value FROM CampaignProperty AS cp LEFT JOIN PropertyValue AS pv ON cp.Id = pv.CampaignPropertyId WHERE cp.Name = "Property1" AND pv.ContactId = c.Id AND cp.CampaignId = c.ActiveCampaignId) AS "Property1"
,(SELECT pv.Value FROM CampaignProperty AS cp LEFT JOIN PropertyValue AS pv ON cp.Id = pv.CampaignPropertyId WHERE cp.Name = "Property2" AND pv.ContactId = c.Id AND cp.CampaignId = c.ActiveCampaignId) AS "Property2"
,(SELECT pv.Value FROM CampaignProperty AS cp LEFT JOIN PropertyValue AS pv ON cp.Id = pv.CampaignPropertyId WHERE cp.Name = "Property3" AND pv.ContactId = c.Id AND cp.CampaignId = c.ActiveCampaignId) AS "Property3"
FROM Contact c

У меня проблема в том, что я сделал для более чем 10 свойств, у меня есть пара LEFT JOIN инесколько фильтров, которые делают мой запрос невероятно неэффективным.Проанализировав это в студии SQL Management, я понял, что узким местом являются те SELECT, которые я показал выше.

Как я могу получить тот же результат, но с лучшей производительностью?Есть ли другой способ выполнить запрос?

Важно также отметить, что таблица PropertyValue не имеет индексов на данный момент ...

Ответы [ 3 ]

0 голосов
/ 05 июня 2018

Это немного сложно из-за нескольких уровней объединения.Я думаю, что вы хотите:

SELECT cp.ContactId,
       MAX(CASE WHEN cp.Name = 'Property1' THEN pv.CampaignProperty END) as Property1,
       MAX(CASE WHEN cp.Name = 'Property2' THEN pv.CampaignProperty END) as Property2,
       MAX(CASE WHEN cp.Name = 'Property3' THEN pv.CampaignProperty END) as Property3
FROM Contact c LEFT JOIN
     CampaignProperty cp
     ON cp.ContactId = c.id AND
        cp.CampaignId = c.ActiveCampaignId LEFT JOIN
     PropertyValue pv
     ON cp.Id = pv.CampaignPropertyId
FROM Contact c
GROUP BY c.Id;

Для производительности вам нужны индексы на CampaignProperty(ContactId, CampaignId, Id, Name) и PropertyValue(CampaignPropertyId, CampaignProperty).

0 голосов
/ 05 июня 2018

Если вы можете жить с несколькими рядами

SELECT c.ID, cp.Name, pv.Value 
  FROM Contact c     
  JOIN CampaignProperty AS cp 
    ON cp.CampaignId = c.ActiveCampaignId  
   AND cp.Name IN ('Property1', 'Property2', 'Property3')       
  LEFT JOIN PropertyValue AS pv 
    ON cp.Id = pv.CampaignPropertyId 
   AND pv.ContactId = c.Id 
 ORDER BY c.ID, cp1.Name
0 голосов
/ 05 июня 2018

Вы можете сделать с помощью одного оператора SELECT и выполнить агрегирование :

select c.id, max(case when cp.Name = 'Property1' then cp.value end) as Property1,
             max(case when cp.Name = 'Property2' then cp.value end) as Property2,
             max(case when cp.Name = 'Property3' then cp.value end) as Property3
from Contact c left join 
     CampaignProperty cp 
     on c.id = cp.ContactId left join
     PropertyValue pl 
     on pl.CampaignPropertyId = cp.id
group by c.id;
...