2014-09-17 6 views
0

У меня есть этот SQL-запрос:комплекс SQL запросов - Time Out

WITH CTE(documents, pocname, pocphone, initialticketNo) 
AS 
(
    SELECT 
     SO.Documents, SO.POCName, SO.POCPhone, 
     SUBSTRING(SO.Documents, 0, CHARINDEX('-', SO.Documents)) AS 'InitialCustomerTicket' 
    FROM 
     ServiceOrder SO 
    CROSS APPLY 
     (SELECT 
      COUNT(TECHNICIANTRIPDETAILID) TTL 
     FROM 
      TECHNICIANTRIPDETAIL 
     WHERE 
      SERVICEORDERID = SO.SERVICEORDERID 
      AND ISEQUIPMENTREPAIRED = 1) EQUIPMENT 
    INNER JOIN 
     Contract CON ON CON.ContractId = SO.ContractId 
    INNER JOIN 
     ClientProfile CP ON CP.ClientId = CON.ClientId 
    WHERE 
     CP.ClientId = 20739 
     AND SO.CloseStatus = 1 
     AND equipment.ttl > 0 
     AND ISNULL(SO.DOCUMENTS,'') <> '' 
) 
SELECT * 
FROM cte 
WHERE initialticketNo <> '' 

Теперь в приведенном выше запросе, если вы видите, я вычислил одно поле initialticketno. Я хочу снова запустить запрос на одном и том же сервисе обслуживания стола и подсчитать количество каждого номера билета, начинающегося с initialticketno. Когда я делаю это, как показано ниже, это занимает много времени, есть ли способ упростить этот запрос?

WITH CTE(documents,pocname,pocphone,initialticketNo) 
as 
(Select SO.Documents,SO.POCName,SO.POCPhone, 
SUBSTRING(SO.Documents,0,CHARINDEX('-',SO.Documents)) AS 'InitialCustomerTicket' 
From ServiceOrder SO 
CROSS APPLY (SELECT COUNT(TECHNICIANTRIPDETAILID) TTL FROM TECHNICIANTRIPDETAIL WHERE SERVICEORDERID = SO.SERVICEORDERID AND ISEQUIPMENTREPAIRED = 1) EQUIPMENT 
Inner Join Contract CON ON CON.ContractId = SO.ContractId 
Inner Join ClientProfile CP ON CP.ClientId = CON.ClientId 
where CP.ClientId = 20739 AND SO.CloseStatus = 1 and equipment.ttl > 0 AND ISNULL(SO.DOCUMENTS,'') <> '') 
select * from cte 
cross apply (select count(serviceorderid) ttl from serviceorder so where so.documents like cte.initialticketNo + '%') as so 
where initialticketNo <> '' and so.ttl > 1 

PS: Всего записей в таблице сервисов составляет 75k.

Может ли кто-нибудь помочь мне в этом.

+0

Как долго слишком долго, вы отменяя исполнения или она достигает кепку – JsonStatham

+0

Он берет 3 до 4 минут время выполнения. –

ответ

0

Держу пари, что вам не хватает индексов, если это так медленно, а ваш набор данных такой маленький. Я думаю, что этот запрос даст тот же результат, но я думаю, что это будет более эффективно.

SELECT DISTINCT 
     SO.Documents, SO.POCName, SO.POCPhone, 
     SUBSTRING(SO.Documents, 0, CHARINDEX('-', SO.Documents)) AS 'InitialCustomerTicket' 
    FROM ServiceOrder SO 
    INNER JOIN Contract CON ON CON.ContractId = SO.ContractId 
    INNER JOIN ClientProfile CP ON CP.ClientId = CON.ClientId 
    INNER JOIN TECHNICIANTRIPDETAIL TTD ON TTD.SERVICEORDERID = SO.SERVICEORDERID 
      AND TTD.ISEQUIPMENTREPAIRED = 1 
    WHERE 
     CP.ClientId = 20739 
     AND SO.CloseStatus = 1 
     AND ISNULL(SO.DOCUMENTS,'') <> '' 
     and SUBSTRING(SO.Documents, 0, CHARINDEX('-', SO.Documents)) <> '' 
+0

Советник по настройке ядра базы данных - это хороший способ определения любых индексов и статистики, которые помогут снизить стоимость рабочей нагрузки. – JsonStatham

0

Проблема Cross Apply. Это будет запускать этот запрос для каждой строки, поэтому, вероятно, 75 тыс. Раз. Имея применяется 2 крест, по крайней мере в два раза хуже;)

Первый запрос может быть переписан как этот

SELECT 
     SO.Documents, SO.POCName, SO.POCPhone, 
     SUBSTRING(SO.Documents, 0, CHARINDEX('-', SO.Documents)) AS 'InitialCustomerTicket' 
    FROM 
     ServiceOrder SO 
    join TECHNICIANTRIPDETAIL on SERVICEORDERID = SO.SERVICEORDERID AND ISEQUIPMENTREPAIRED = 1 as 'EQUIPMENT' 
    INNER JOIN 
     Contract CON ON CON.ContractId = SO.ContractId 
    INNER JOIN 
     ClientProfile CP ON CP.ClientId = CON.ClientId 
    WHERE 
     CP.ClientId = 20739 
     AND SO.CloseStatus = 1 
     AND ISNULL(SO.DOCUMENTS,'') <> '' 
    Group by SO.Documents, SO.POCName, SO.POCPhone, 
     SUBSTRING(SO.Documents, 0, CHARINDEX('-', SO.Documents)) AS 'InitialCustomerTicket' 
    having count(equipment.TECHNICIANTRIPDETAILID) > 0 

Второй может быть записана следующим образом:

SELECT 
     SO.Documents, SO.POCName, SO.POCPhone, 
     SUBSTRING(SO.Documents, 0, CHARINDEX('-', SO.Documents)) AS 'InitialCustomerTicket' 
    FROM 
     ServiceOrder SO 
    join TECHNICIANTRIPDETAIL on SERVICEORDERID = SO.SERVICEORDERID AND ISEQUIPMENTREPAIRED = 1 as 'EQUIPMENT' 
    INNER JOIN 
     Contract CON ON CON.ContractId = SO.ContractId 
    INNER JOIN 
     ClientProfile CP ON CP.ClientId = CON.ClientId 
    join serviceorder as SO2 on so2.documents like so.initialticketNo + '%' 
    WHERE 
     CP.ClientId = 20739 
     AND SO.CloseStatus = 1 
     AND ISNULL(SO.DOCUMENTS,'') <> '' 
    Group by SO.Documents, SO.POCName, SO.POCPhone, 
     SUBSTRING(SO.Documents, 0, CHARINDEX('-', SO.Documents)) AS 'InitialCustomerTicket' 
    having count(equipment.TECHNICIANTRIPDETAILID) > 0 
     and count(so2.serviceorderid) > 1 

Конечно , Я не могу запустить до и после, потому что у меня нет данных, но я думаю, что это нужно делать. Если это не по крайней мере дает вам представление о том, где взять голову - удалите Cross Apply, когда это возможно.

0

Это проще и (вероятно) более эффективный запрос:

SELECT SO.Documents , 
     SO.POCName , 
     SO.POCPhone , 
     SUBSTRING(SO.Documents, 0, CHARINDEX('-', SO.Documents)) AS initialticketNo 
FROM ClientProfile CP 
     INNER JOIN [Contract] CON ON CON.ClientId = CP.ClientId 
     INNER JOIN ServiceOrder SO ON SO.ContractId = CON.ContractId 
WHERE CP.ClientId = 20739 
     AND SO.CloseStatus = 1 
     AND SO.Documents IS NOT NULL 
     AND SO.Documents LIKE '%-%' 
     AND EXISTS (SELECT * 
        FROM TECHNICIANTRIPDETAIL TTL 
        WHERE TTL.ISEQUIPMENTREPAIRED = 1 
        AND TTL.SERVICEORDERID = SO.SERVICEORDERID)