Подзапрос Построение столбца - PullRequest
0 голосов
/ 16 ноября 2018

Мне интересно, есть ли более эффективный способ выполнить следующий запрос.

SELECT 
t.iCertification_UserCertificationTranscriptID  AS I_CERT_TRANSCRIPT_DIM, 
t.iHR_UserID                                    AS I_EMP_DIM, 
t.iCertification_CertificationID                AS I_RUL_CERT_DIM,
(
    SELECT iHR_PositionID
    FROM UserProfileNoGroups AS prof
    WHERE 
        (iHR_UserID = t.iHR_UserID) 
        AND (Profile_IsPrimary = '1') 
        AND (UserPosition_IsPrimary = '1') 
        AND (t.dEffectiveStart BETWEEN UserPosition_Effective AND COALESCE(UserPosition_End, LOCALTIMESTAMP))
    ORDER BY UserPosition_Effective DESC
    FETCH FIRST 1 ROWS ONLY
) AS I_POSN_DIM,                                    
CAST(EXTRACT(YEAR FROM t.dEffectiveStart) * 10000 + EXTRACT(MONTH FROM t.dEffectiveStart) * 100 + EXTRACT(DAY FROM t.dEffectiveStart) AS INT)   AS I_DAY_STRT_DIM, 
CAST(EXTRACT(YEAR FROM t.dEffectiveEnd) * 10000 + EXTRACT(MONTH FROM t.dEffectiveEnd) * 100 + EXTRACT(DAY FROM t.dEffectiveEnd) AS INT)         AS I_DAY_END_DIM,  
CASE 
    WHEN t.iCertification_TranscriptSourceID = '1' THEN 'Y' 
    ELSE 'N' 
END                                     AS L_AdminOverride,
t.mComment                          AS X_Comment
FROM 
dbo.tCertification_UCT AS t;

Меня беспокоит запрос, который строит столбец I_POSN_DIM. Запрос выполняется медленно, и кажется, что этот запрос нужно сканировать снова и снова, чтобы извлечь результаты. Это в postgresql, и я не очень знаком с этой платформой. Я попытался использовать CTE, которые используют функцию MAX, но COUNT всегда оказывается отличным от этого запроса. Любая помощь будет оценена.

1 Ответ

0 голосов
/ 16 ноября 2018

Я подумал примерно так:

SELECT 
t.iCertification_UserCertificationTranscriptID  AS I_CERT_TRANSCRIPT_DIM, 
t.iHR_UserID                                    AS I_EMP_DIM, 
t.iCertification_CertificationID                AS I_RUL_CERT_DIM,
uPG.iHR_PositionID                              AS I_POSN_DIM,                                    
(t.dEffectiveStart.Year * 10000 + t.dEffectiveStart.Month * 100 +  t.dEffectiveStart.Day)   AS I_DAY_STRT_DIM, 
(t.dEffectiveEnd.Year * 10000 + t.dEffectiveEnd.Month * 100 + t.dEffectiveEnd.Day)         AS I_DAY_END_DIM,  
CASE WHEN t.iCertification_TranscriptSourceID = '1' THEN 'Y' ELSE 'N' END                                                                       AS L_AdminOverride,
t.mComment                                      AS X_Comment
FROM dbo.tCertification_UCT AS t
INNER JOIN UserProfileNoGroups uPG ON t.iHR_UserID = uPG.iHR_UserID
WHERE Profile_IsPrimary = '1'
        AND UserPosition_IsPrimary = '1'
        AND (t.dEffectiveStart BETWEEN UserPosition_Effective AND COALESCE(UserPosition_End, LOCALTIMESTAMP));

Я переместил внутренний запрос наружу и преобразовал его в эквивалентное внутреннее соединение.В других полях, которые вы произвели, но это не обязательно, потому что результатом этих операций является int.

Но я предположил, что таблица UserProfileNoGroups имеет 1 запись для каждой записи в tCertification_UCT.Если это не так, запрос изменил бы немного:

SELECT 
t.iCertification_UserCertificationTranscriptID  AS I_CERT_TRANSCRIPT_DIM, 
t.iHR_UserID                                    AS I_EMP_DIM, 
t.iCertification_CertificationID                AS I_RUL_CERT_DIM,
uPG.iHR_PositionID  OVER (ORDER BY UserPosition_Effective DESC)                         AS I_POSN_DIM,                                    
(t.dEffectiveStart.Year * 10000 + t.dEffectiveStart.Month * 100 +  t.dEffectiveStart.Day)   AS I_DAY_STRT_DIM, 
(t.dEffectiveEnd.Year * 10000 + t.dEffectiveEnd.Month * 100 + t.dEffectiveEnd.Day)         AS I_DAY_END_DIM,  
CASE WHEN t.iCertification_TranscriptSourceID = '1' THEN 'Y' ELSE 'N' END                              AS L_AdminOverride,
t.mComment                                      AS X_Comment
FROM dbo.tCertification_UCT AS t
INNER JOIN UserProfileNoGroups uPG ON t.iHR_UserID = uPG.iHR_UserID
WHERE Profile_IsPrimary = '1'
        AND UserPosition_IsPrimary = '1'
        AND (t.dEffectiveStart BETWEEN UserPosition_Effective AND COALESCE(UserPosition_End, LOCALTIMESTAMP));

Вы можете играть с предложением OVER:

https://www.postgresql.org/docs/9.1/tutorial-window.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...