2015-07-29 12 views
7

Burada gerçek bir akıl karıştırıcı var!Çapraz tablo değerli bir işlev uygular

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 burada eşsiz bir alandır ancak bu sorgu kullanıcı o gün için girildiğinden birden ligleri döndürür göreceksiniz:

Ben temelde bir lig kullanıcıları konumlandırır bir tablo var.

Ayrıca, lig için geçerli ödül puanlarını döndüren bir tablo değeri işlevim var ve bu, bir parametre olarak LeagueID'yi kabul eder ve ödül parası almaya hak kazanan kişileri döndürür. Bu, ideal olarak LeagueID'yi kabul eden işlev olarak tutmak istediğim karmaşık bir işlevdir. Bunun sonucu olarak aşağıdaki gibidir:

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 

Esasen ne yapmak istediğim esasen o League_EntryID yani

için Ödül alan güncelleştirmeye LigID ileterek üstteki sorguya tablo değeri işlevini katılmaktır
SELECT * FROM [League] 
INNER JOIN [League_Entry] ON [League].[LeagueID] = [League_Entry].[LeagueID] 
INNER JOIN [dbo].[GetPrizesForLeague]([League].[LeagueID]) .... 

CROSS APPLY'nin işe yarayıp yaramayacağından emin değilim ama aslında LeagueID ve League_EntryID'de JOIN'e ödülüm için bana değer vermem gerektiğine inanıyorum. Bunu skaler bir işlevi ziyaret etmeden yapmanın en iyi yolundan emin olamayacaksınız; bu da sırayla tablo değeri işlevini çağırır ve bundan Ödül kazanır.

Hız beni burada endişelendiriyor.

P.S. Tüm Lig_EntryID'leri tablo değeri fonksiyonunun bir parçası olarak mevcut olmayabilir, bu yüzden bir DIŞ JOIN/APPLY kullanılabilir mi?

DÜZENLEME

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] 

herhangi bir yönü, aşağıdaki sorgu takdir bakınız.

+0

Performansı iyileştirmede yardıma ihtiyacınız varsa, tüm ayrıntıları içeren bir soru yayınlamanız gerekir: tablo ve dizin yapısı, sahip olduğunuz geçerli kod ve örnek veriler + beklenen sonuçlar, tercihen SQL Fiddle. Eğer işlev örneğin bir satır içi işleve dönüştürülebiliyorsa, performans çok daha iyi olmalı, ama tabiki bu durumda çok fazla bir şey var. –

cevap

3

DIŞ APPLY (CROSS UYGULAMASI ve SOL JOIN) karışımını kullanmanız gerekir.

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

CROSS APPLY/OUTER APPLY ile performans çok iyidir. Bazı iç sorguları ve imleçleri değiştirmek için harika.

+0

Eğer bu fonksiyon çok yönlü bir UDF ise, performans gerçekten çok kötü olabilir. temelde bir imleç. Fonksiyon, sonuç kümesindeki her satır için ayrı ayrı yürütülür ve bunun maliyeti, sorgu planında veya istatistik çıkışında bile görünmez. –

+0

Ayrıca, fonksiyonun dışına seçim yapmak yerine sadece * uygulayabilirsiniz * –

+0

Artık bu bir çift kopya yükü geri getiriyor gibi görünüyor ve bunun benzersiz bir sıraya katılmadığından emin değilim (lig_entryID) – CR41G14

İlgili konular