2013-11-27 76 views
0

我試圖做一個存儲在SQL服務器功能,它將返回我可以加入回到另一個表中值的表,正是如此:列別名錯誤與SQL Server UDF

CREATE FUNCTION [dbo].getmedian (@varPartionBy1 int,@varPartionBy2 int, @varForTieBreak int, @varForMeasure int) 
    RETURNS TABLE 
    AS 
    RETURN 
    (
     SELECT 
      @varPartionBy1, 
      @varPartionBy2, 
      AVG(@varForMeasure) 
     FROM 
     (
      SELECT 
       @varPartionBy1, 
       @varPartionBy2, 
       ROW_NUMBER() OVER (
       PARTITION BY @varPartionBy1, @varPartionBy2 
       ORDER BY @varForMeasure ASC, @varForTieBreak ASC) AS RowAsc, 
       ROW_NUMBER() OVER (
       PARTITION BY @varPartionBy1, @varPartionBy2 
       ORDER BY @varForMeasure ASC, @varForTieBreak DESC) AS RowDesc 
      from 
      [fakename].[dbo].[temptable] bp 

     ) bp 
     WHERE 
      RowAsc IN (RowDesc, RowDesc - 1, RowDesc + 1) 
     GROUP BY @varPartionBy1, @varPartionBy2 

    ) 

GO

這是返回錯誤:「消息8155,級別16,狀態2,過程getmedian,第25行 沒有列名的‘BP’第1欄指明。」 - 我想,我不明白如何在UDF上下文中爲列設置表別名。

我應該怎麼做來解決這個錯誤嗎?

這是我的第一個USF所以我很感謝你,而解決這些問題的主要問題的任何其他有用的設計見解。謝謝你的幫助!

+1

在你的內部select中,爲變量提供一個別名,'@ varPartionBy1 as varPartionBy1',然後在外部select中調用新的別名而不是變量。 – Taryn

+0

我建議你創建一個問題,這顯示了一些在不是Temptable樣本數據,然後顯示什麼結果,你根據給定的參數值期待。在這裏,我無法從代碼中推斷出這實際上應該做什麼。 –

回答

2

如果你有SELECT @varPartionBy1, @varPartionBy2那些需要有分配給他們的列名。您可以將它們分配直接如SELECT @varPartionBy1 AS varPartionBy1SELECT varPartionBy1 = @varPartionBy1也可以在表的別名) bp(varPartionBy1, varPartionBy2,...

指定了正確的功能很可能是

CREATE FUNCTION [dbo].getmedian (@varPartionBy1 int,@varPartionBy2 int, @varForTieBreak int, @varForMeasure int) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT 
     varPartionBy1, 
     varPartionBy2, 
     AVG(@varForMeasure) AS AvgVarForMeasure 
    FROM 
    (
     SELECT 
      @varPartionBy1 AS varPartionBy1, 
      @varPartionBy2 As varPartionBy1, 
      ROW_NUMBER() OVER (
      PARTITION BY @varPartionBy1, @varPartionBy2 
      ORDER BY @varForMeasure ASC, @varForTieBreak ASC) AS RowAsc, 
      ROW_NUMBER() OVER (
      PARTITION BY @varPartionBy1, @varPartionBy2 
      ORDER BY @varForMeasure ASC, @varForTieBreak DESC) AS RowDesc 
     from 
     [fakename].[dbo].[temptable] bp 

    ) bp 
    WHERE 
     RowAsc IN (RowDesc, RowDesc - 1, RowDesc + 1) 
    GROUP BY varPartionBy1, varPartionBy2 

) 
+0

謝謝!我猜根據Aaron Bertrand的評論,這個決議並不能解決我所有的問題,但至少我已經知道了這個問題的答案。 – ouonomos

1

好了,一旦你的語法問題的出路,你的問題不會結束。首先,你不能真正做你想要做什麼(傳遞變量的PARTITION BYORDER BY條款)。那些只是被視爲常量,所以ROW_NUMBER()將被任意使用。

觀察這裏發生了什麼:

DECLARE @foo SYSNAME = N'name'; 

SELECT name, foo = @foo, -- this is just a constant value, not a column 
    varASC = ROW_NUMBER() OVER (ORDER BY @foo ASC), 
    varDESC = ROW_NUMBER() OVER (ORDER BY @foo DESC), 
    colASC = ROW_NUMBER() OVER (ORDER BY name ASC), 
    colDESC = ROW_NUMBER() OVER (ORDER BY name DESC) 
FROM sys.objects --WHERE is_ms_shipped = 0 
ORDER BY varASC; 

部分結果:

name foo varASC varDESC colASC colDESC 
---- ---- ------ ------- ------ ------- 
t1 name  1  1  1  100 
t2 name  2  2  2  99 
t3 name  3  3  3  98 
t4 name  4  4  4  97 
t5 name  5  5  5  96 
------ only column that deviates ----^^^^^^^ 

@foo變量值是每一行相同,因此,劃分和排序由完全無意義的。

+0

轉到使用動態sql? –

+0

@CRAFTYDBA在函數中?我不這麼認爲。 –

+0

我不好,我以爲這是一個SP。但是具有動態SQL的SP可能是一個解決方案。沒有足夠的業務需求來進行判斷。 –