У меня есть запрос или группа запросов, которые я просто не могу воспроизвести: :)
SELECT
C.ID AS cust_id,
C.State AS cust_state,
C.PrevState AS cust_previous_state,
C.ProjectID AS cust_imported_on_project_id,
C.CampaignID AS cust_imported_on_campaign_id,
C.Priority AS cust_priority,
C.Name AS cust_firstname,
C.Name2 AS cust_lastname,
C.AllocatedUser AS cust_allocated_user,
C.ED1 AS cust_social_security_number,
C.ED2 AS cust_customer_number,
C.ED3 AS cust_type,
C.ED4 AS cust_initial_fact_1,
C.ED5 AS cust_initial_fact_2,
C.ED6 AS cust_initial_fact_3,
C.ED7 AS cust_initial_fact_4,
C.ED8 AS cust_initial_fact_5,
C.ED9 AS cust_extra_1,
C.ED10 AS cust_extra_2,
CED2.ED11 AS cust_extra_3,
CED2.ED12 AS cust_extra_4,
CED2.ED13 AS cust_extra_5,
A.Serial AS address_serial,
A.PostAddress AS address_postal_address,
A.PostCode AS address_postal_code,
A.PostOffice AS address_city,
A.PhoneNr AS address_phonenumber,
A.FaxNr AS address_faxnumber,
A.EMail AS address_email,
A.Notes AS address_notes,
A.ED1 AS address_secondary_phonenumber,
A.ED2 AS address_origin_file,
A.State AS address_state
FROM TCustomers C WITH (NOLOCK)
LEFT JOIN TCustED2 CED2 WITH (NOLOCK) ON C.ID = CED2.CustomerID
LEFT JOIN TAddresses A WITH (NOLOCK) ON C.AddressNr = A.Serial AND C.ID = A.CustomerID
WHERE C.CampaignID IN(SELECT items FROM dbo.Split('196,195,210,206,205,207,204,200,209,213,197,198,214', ',')) AND C.InsDate > '2011-04-03 00:00:00'
Этот запрос сам по себе очень быстрый и выполняется за несколько миллионов строк за несколько секунд.
Проблема в том, что я хочу использовать информацию из таблицы заказов для фильтрации своих результатов.
Я пытался присоединиться к таблице заказов
SELECT
C.ID AS cust_id,
C.State AS cust_state,
C.PrevState AS cust_previous_state,
C.ProjectID AS cust_imported_on_project_id,
C.CampaignID AS cust_imported_on_campaign_id,
C.Priority AS cust_priority,
C.Name AS cust_firstname,
C.Name2 AS cust_lastname,
C.AllocatedUser AS cust_allocated_user,
C.ED1 AS cust_social_security_number,
C.ED2 AS cust_customer_number,
C.ED3 AS cust_type,
C.ED4 AS cust_initial_fact_1,
C.ED5 AS cust_initial_fact_2,
C.ED6 AS cust_initial_fact_3,
C.ED7 AS cust_initial_fact_4,
C.ED8 AS cust_initial_fact_5,
C.ED9 AS cust_extra_1,
C.ED10 AS cust_extra_2,
CED2.ED11 AS cust_extra_3,
CED2.ED12 AS cust_extra_4,
CED2.ED13 AS cust_extra_5,
A.Serial AS address_serial,
A.PostAddress AS address_postal_address,
A.PostCode AS address_postal_code,
A.PostOffice AS address_city,
A.PhoneNr AS address_phonenumber,
A.FaxNr AS address_faxnumber,
A.EMail AS address_email,
A.Notes AS address_notes,
A.ED1 AS address_secondary_phonenumber,
A.ED2 AS address_origin_file,
A.State AS address_state
FROM TCustomers C WITH (NOLOCK)
LEFT JOIN TCustED2 CED2 WITH (NOLOCK) ON C.ID = CED2.CustomerID
LEFT JOIN TAddresses A WITH (NOLOCK) ON C.AddressNr = A.Serial AND C.ID = A.CustomerID
LEFT JOIN TOrders O WITH (NOLOCK) ON C.ID = O.CustomerID
WHERE C.CampaignID IN(SELECT items FROM dbo.Split('196,195,210,206,205,207,204,200,209,213,197,198,214', ',')) AND
(C.InsDate > '2011-04-03 00:00:00' OR O.CustomerID NOT NULL OR O.[Date] > '2011-04-03 00:00:00' OR O.Exported IS NULL);
В результате время выполнения составляет несколько минут.
Если я просто запускаю интересную часть из TOrders
, это займет несколько секунд.
SELECT CustomerID
FROM TOrders
WHERE O.CustomerID NOT NULL
OR O.[Date] > '2011-04-03 00:00:00'
OR O.Exported IS NULL;
Так что проблема в том, как объединить два. Я попытался запустить запрос TOrders и вставить полученные CustomerID непосредственно в основной запрос, и это было быстро и заняло около 5-10 секунд. Я попытался предварительно загрузить интересные данные из TOrders и поместить их во временную таблицу, но это не помогло ускорить процесс.
CREATE TABLE #ORDERCUSTOMERS (
CustomerID int
);
CREATE UNIQUE CLUSTERED INDEX IX_1 on #ORDERCUSTOMERS (CustomerID);
INSERT #ORDERCUSTOMERS SELECT DISTINCT O.CustomerID FROM LPD1_8.dbo.TOrders O WHERE O.CampaignID IN(SELECT items FROM dbo.Split('196,195,210,206,205,207,204,200,209,213,197,198,214', ',')) AND (O.[Date] > '2011-04-03 00:00:00' OR O.Exported IS NULL);
SELECT
C.ID AS cust_id,
C.State AS cust_state,
C.PrevState AS cust_previous_state,
C.ProjectID AS cust_imported_on_project_id,
C.CampaignID AS cust_imported_on_campaign_id,
C.Priority AS cust_priority,
C.Name AS cust_firstname,
C.Name2 AS cust_lastname,
C.AllocatedUser AS cust_allocated_user,
C.ED1 AS cust_social_security_number,
C.ED2 AS cust_customer_number,
C.ED3 AS cust_type,
C.ED4 AS cust_initial_fact_1,
C.ED5 AS cust_initial_fact_2,
C.ED6 AS cust_initial_fact_3,
C.ED7 AS cust_initial_fact_4,
C.ED8 AS cust_initial_fact_5,
C.ED9 AS cust_extra_1,
C.ED10 AS cust_extra_2,
CED2.ED11 AS cust_extra_3,
CED2.ED12 AS cust_extra_4,
CED2.ED13 AS cust_extra_5,
A.Serial AS address_serial,
A.PostAddress AS address_postal_address,
A.PostCode AS address_postal_code,
A.PostOffice AS address_city,
A.PhoneNr AS address_phonenumber,
A.FaxNr AS address_faxnumber,
A.EMail AS address_email,
A.Notes AS address_notes,
A.ED1 AS address_secondary_phonenumber,
A.ED2 AS address_origin_file,
A.State AS address_state
FROM LPD1_8.dbo.TCustomers C WITH (NOLOCK)
LEFT JOIN LPD1_8.dbo.TCustED2 CED2 WITH (NOLOCK) ON C.ID = CED2.CustomerID
LEFT JOIN LPD1_8.dbo.TAddresses A WITH (NOLOCK) ON C.AddressNr = A.Serial AND C.ID = A.CustomerID
LEFT JOIN #ORDERCUSTOMERS O ON C.ID = O.CustomerID
WHERE C.CampaignID IN(SELECT items FROM dbo.Split('196,195,210,206,205,207,204,200,209,213,197,198,214', ',')) AND
(C.InsDate > '2011-04-03 00:00:00' OR O.CustomerID NOT NULL);
DROP TABLE #ORDERCUSTOMERS;
Так у вас, ребята, есть идеи? Это будет храниться в хранимой процедуре, поэтому я хочу избежать динамического SQL, если это возможно. В противном случае это, вероятно, будет одним из способов получить данные из TOrders и вставить возвращенные идентификаторы CustomerID в предложение IN основного запроса.
Но, возможно, есть аналогичный способ «вставить» массив идентификаторов в предложение IN или что-то в этом роде?