SQL Cross Apply - нужно ли это - неясно, почему он используется в этом примере

Я работаю над хранимой процедурой, которую я унаследовал, и у нее есть несколько запросов перекрестного применения (см. запросы ниже). У меня есть опытный разработчик SQL, но не так много для перекрестного применения, поэтому может быть простое объяснение, которое мне здесь просто не хватает.

Мой вопрос заключается в том, что для этих двух запросов похоже, что перекрестное применение просто выполняет вызов функции и/или логику для создания столбца, и я мог бы просто сделать это при выборе и полностью удалить перекрестное применение. Если бы вы могли дать какое-то объяснение, почему я тоже был бы признателен.

Когда я видел использование перекрестного применения, всегда было что-то В перекрестном применении, которое по существу соединялось бы с таблицами вне перекрестного применения. Что-то вроде этого, например, будет внутри кросс-приложения для «присоединения» таблиц FROM к таблицам в кросс-приложении: soh.SalesOrderID (таблица вне corss) = sod.SalesOrderID (таблица внутри кросса)

Я не вижу ничего подобного в приведенных ниже 2 запросах или причинах этого.

        SELECT 
            LeadInventory.LoanNumber, 
            'Client Age',
            PEMWeightByClientAge.PEMWeight,
            LeadInventory.ClientAge,
            PEMWeightByClientAge.PEMWeight,
             #LoanPEMModelHybrid.PEMModel 
        FROM LeadInventory  
        INNER JOIN #LoanPEMModelHybrid ON dbo.LeadInventory.LoanNumber = #LoanPEMModelHybrid.LoanNumber 
        CROSS APPLY 
        (
            SELECT PEMWeight =
            CASE 
                WHEN LeadInventory.ClientAge<=70 AND LeadInventory.ClientAge>=62 Then @PEMWeightAge62To70
                WHEN LeadInventory.ClientAge<80 AND LeadInventory.ClientAge>70 THEN @PEMWeightAge71To80
                WHEN LeadInventory.ClientAge>=80 THEN @PEMWeightAge80Plus
            ELSE 0
            END
        ) AS  PEMWeightByClientAge     
        WHERE #LoanPEMModelHybrid.PEMModel = 'Application' 
        AND LeadInventory.ClientAge>0





SELECT  DISTINCT 
        IDENTITY(INT, 1,1) AS ID,
        LoanNumber,
        Calculation.Prob AS TotalPEMScoreForLoan,
        PEMModelCode
INTO #PEMScoreHybridFinal
FROM #PEMScoreHybrid    
CROSS APPLY
( 
  SELECT Prob  = 
  CASE PEMModelCode
       WHEN 'Initial QQ' THEN CAST (EXP(@INITIALQQBASE+ TotalPEMScoreForLoan)/(EXP(@INITIALQQBASE+TotalPEMScoreForLoan)+1)*100 AS Decimal(9,2)) 
       WHEN 'APPLICATION' THEN CAST (EXP(@APPLICATIONBASE+ TotalPEMScoreForLoan)/(EXP(@APPLICATIONBASE+TotalPEMScoreForLoan)+1)*100 AS Decimal(9,2)) 
       END
) Calculation   

Спасибо.


person Brad    schedule 20.10.2016    source источник
comment
По моему вы совершенно правы. Это просто неудобный синтаксис. Если бы я писал сценарий, я бы либо сделал его функцией, либо включил в оператор select. Однако я не уверен, что стал бы его рефакторить, если он уже работает как есть.   -  person David Cram    schedule 20.10.2016


Ответы (1)


В первом запросе вы можете использовать подзапрос. Однако обратите внимание, что переменная PEMWeightByClientAge.PEMWeight в CROSS APPLY используется дважды в SELECT. Это дает подсказку, почему запись выбрала CROSS APPLY.

Почему вы используете CROSS APPLY? Есть несколько причин. Самым простым является вызов функции, возвращающей множество, для аргументов из таблицы. На самом деле нет другого способа сделать это.

С подзапросом APPLY является более общим, чем соединения. Он также может оптимизировать лучше. Если вас не устраивает специфичный для SQL-сервера APPLY, просто поймите, что это боковые соединения, вполне совместимые с другими операциями с базой данных.

У вас есть третий вариант использования. Это позволяет обойти тот факт, что псевдонимы столбцов нельзя повторно использовать в файле SELECT. Подзапросы и CTE являются альтернативой. У подзапросов есть обратная сторона (при правильном отступе) вложенность может оставить много пустого места слева. CTE являются жизнеспособной альтернативой. Что кто-то использует, это действительно вопрос вкуса, а не «правильно» или «неправильно».

person Gordon Linoff    schedule 20.10.2016