2015-07-29 18 views
7

Una vera mente bender qui ragazzi!Croce applicare una funzione valutata tabella

Ho una tabella che posiziona sostanzialmente gli utenti in un campionato:

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 

Il League_EntryID è il campo unico qui, ma si vedrà questa query restituisce più campionati che l'utente è entrato per quel giorno.

Ho anche una funzione del valore di tabella che restituisce la classifica dei premi correnti per il campionato e accetta il LeagueID come parametro e restituisce le persone che si qualificano per il montepremi. Questa è una funzione complessa che idealmente vorrei mantenere come funzione che accetta il LeagueID. Il risultato di ciò è la seguente:

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 

Essenzialmente quello che voglio fare è quello di unire la funzione valore tabella alla query più alto passando l'LeagueID per aggiornare essenzialmente Campo premio per tale League_EntryID cioè

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

Non sono sicuro che una CROSS APPLY possa funzionare qui, ma in sostanza credo di aver bisogno di unirsi sia a LeagueID che a League_EntryID per darmi il mio valore per il premio. Non sei sicuro del modo migliore per farlo senza visitare una funzione scalare che a sua volta chiamerà la funzione del valore di tabella e otterrà il Premio da quello.

La velocità mi sta preoccupando.

P.S. Non tutti i League_EntryID esisteranno come parte dell'output della funzione value table, quindi è possibile utilizzare un JOIN/APPLY OUTER?

EDIT Vedere la domanda sotto

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] 

Qualunque direzione sarebbe apprezzato.

+0

Se hai bisogno di aiuto per migliorare le prestazioni, devi pubblicare una domanda con tutti i dettagli: tabella e struttura dell'indice, il codice corrente che hai e dati di esempio + risultati attesi, preferibilmente in SQL Fiddle. Se la funzione può essere cambiata ad esempio in una funzione inline, le prestazioni dovrebbero essere molto migliori, ma ovviamente dipende molto dal tuo caso –

risposta

3

È necessario utilizzare APPLICAZIONE ESTERNA (un mix di APPLICA CROCE e UNISCI SINISTRA).

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

Le prestazioni sono molto buone con APPLICAZIONI CROSS/APPLICAZIONI ESTERNE. È ottimo per sostituire alcune query interne e cursori.

+0

Se la funzione è un UDF multi statement, le prestazioni possono essere davvero pessime, poiché è fondamentalmente un cursore. La funzione verrà eseguita separatamente per ogni riga nel set di risultati e il suo costo non è nemmeno visibile nel piano di query o nell'output di statistiche io. –

+0

Inoltre, puoi semplicemente applicare la funzione invece di selezionare * da esso –

+0

Sembra che questo ora stia riportando un carico di duplicati e non sono sicuro che si unisca a una riga univoca (il league_entryID) – CR41G14