2015-07-29 4 views
7

Настоящий ум изгиб здесь, ребята!Перекрестная нанести табличную функцию

У меня есть таблица, которая в основном позиционирует пользователь в лиге:

LeagueID Stake League_EntryID UserID TotalPoints TotalBonusPoints Prize 
13028 2.00  58659  2812  15   5    NULL 
13028 2.00  58662  3043  8   3    NULL 
13029 5.00  58665  2812  8   3    NULL 

League_EntryID является уникальным полем здесь, но вы увидите этот запрос возвращает несколько лиг, которые пользователь введенный в этот день.

У меня также есть функция значения таблицы, которая возвращает текущую позицию в лиге для лиги, и это признает лиги в качестве параметра и возвращает людей, которые имеют право на получение призового фонда. Это сложная функция, которую я хотел бы сохранить как функцию, принимающую Лиги. Результат этого является то, как показано ниже:

UserID Position League_EntryID WinPerc  Prize 
2812 1    58659  36.000000 14.00 
3043 6    58662  2.933333 4.40 
3075 6    58664  2.933333 4.40 

По сути то, что я хочу сделать, это присоединиться к функции табличного значения для верхнего запроса путем передачи в LeagueID существенно обновить поле премии за что League_EntryID т.е.

SELECT * FROM [League] 
INNER JOIN [League_Entry] ON [League].[LeagueID] = [League_Entry].[LeagueID] 
INNER JOIN [dbo].[GetPrizesForLeague]([League].[LeagueID]) .... 

Я не уверен, что здесь будет работать CROSS APPLY, но по существу я считаю, что мне нужно ПРИСОЕДИНЯЙТЕСЬ на Лиге и Лиге_EntryID, чтобы дать мне мою ценность для Приза. Не уверен в том, как это сделать, не посещая скалярную функцию, которая, в свою очередь, вызовет функцию значения таблицы и получит от нее Приз.

Скорость меня беспокоит.

P.S. Не все лиги_EntryID будут существовать как часть вывода функции значения таблицы, поэтому, возможно, может использоваться OUTER JOIN/APPLY?

РЕДАКТИРОВАТЬ См запрос ниже

SELECT DISTINCT [LeagueID], 
    [CourseName], 
    [Refunded], 
    [EntryID], 
    [Stake], 
    d.[League_EntryID], 
    d.[UserID], 
    [TotalPoints], 
    [TotalBonusPoints], 
    [TotalPointsLastRace], 
    [TotalBonusPointsLastRace], 
    d.[Prize], 
    [LeagueSizeID], 
    [TotalPool], 
    d.[Position], 
    [PositionLastRace], 
    t.Prize 

FROM 
(
SELECT [LeagueID], 
    [EntryID], 
    [Stake], 
    [MeetingID], 
    [Refunded], 
    [UserID], 
    [League_EntryID], 
    [TotalPoints], 
    [TotalBonusPoints], 
    [TotalPointsLastRace], 
    [TotalBonusPointsLastRace], 
    [Prize], 
    [LeagueSizeID], 
    [dbo].[GetTotalPool]([LeagueID], 1) AS [TotalPool], 
    RANK() OVER(PARTITION BY [LeagueID] ORDER BY [TotalPoints] DESC, [TotalBonusPoints] DESC) AS [Position], 
    RANK() OVER(PARTITION BY [LeagueID] ORDER BY [TotalPointsLastRace] DESC, [TotalBonusPointsLastRace] DESC) AS [PositionLastRace], 
    ROW_NUMBER() OVER (PARTITION BY [LeagueID] 
           ORDER BY [TotalPoints] DESC, [TotalBonusPoints] DESC 
           ) as [Position_Rownum] 
FROM [DATA]) AS d 

INNER JOIN [Meeting] WITH (NOLOCK) ON [d].[MeetingID] = [Meeting].[MeetingID] 
INNER JOIN [Course] ON [Meeting].[CourseID] = [Course].[CourseID] 
OUTER APPLY (SELECT * FROM [dbo].[GetLeaguePrizes](d.[LeagueID])) t 
WHERE (
     ([LeagueSizeID] = 3 AND [Position_Rownum] <= 50) 
     OR (d.[UserID] = @UserID AND [LeagueSizeID] = 3) 
    ) 
     OR 
     (
     [LeagueSizeID] in (1,2) 
    ) 

ORDER BY [LeagueID], [Position] 

Любые направления будут оценены.

+0

Если вам нужна помощь в улучшении производительности, вы должны задать вопрос со всеми подробностями: таблица и структура индекса, текущий код, который у вас есть, и пример данных + ожидаемые результаты, желательно в SQL Fiddle. Если функция может быть изменена, например, на встроенную функцию, производительность должна быть намного лучше, но, конечно, это зависит от вашего случая. –

ответ

3

Вам необходимо использовать OUTER APPLY (соединение CROSS APPLY и LEFT JOIN).

SELECT * FROM [League] 
INNER JOIN [League_Entry] ON [League].[LeagueID] = [League_Entry].[LeagueID] 
OUTER APPLY [dbo].[GetPrizesForLeague]([League].[LeagueID]) t 

Эксплуатационные характеристики очень хороши при использовании КРОССЫ ПРИМЕНЕНИЯ/ВНЕШНЕГО ПРИМЕНЕНИЯ. Это отлично подходит для замены некоторых внутренних запросов и курсоров.

+0

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

+0

Кроме того, вы можете просто использовать внешнюю функцию вместо того, чтобы делать выбор * из нее –

+0

Похоже, что теперь вы возвращаете нагрузку дубликатов, и я не уверен, что это соединение с уникальной строкой (league_entryID) – CR41G14

Смежные вопросы