2017-02-16 3 views
1

Ich versuche, eine einfache Funktion zu schreiben, die es mir erlaubt, die Summe basierend auf dem Wert einer Spalte zu erhalten.SQL Erstellen einer Funktion zum Abrufen der Summe basierend auf dem Spaltennamen

CREATE FUNCTION [GetSumOfColumnByCase](@column varchar(50), @case int) 
    RETURNS INT 
AS 
BEGIN 

    declare @return int 
    set @return = SUM(CASE WHEN @column = @case THEN 1 ELSE 0 END) 

    -- Return the result of the function 
    return @return 

END 
GO 

Ich nenne diese Funktion wie folgt aus:

 SELECT HouseDescription, 
       [dbo].[GetSumOfColumnByCase]([HouseTypeId], 1) AS "houseType1", 
       [dbo].[GetSumOfColumnByCase]([HouseTypeId], 2) AS "houseType2" 

Dinge tun auf diese Weise zwingt mich zu GROUP BY sowohl die houseDescription und die HouseTypeId Spalten, aber ich möchte nur die housedescription GROUP BY.

Wenn ich Dinge tun, auf diese Weise:

SELECT HouseDescription, 
     SUM(CASE WHEN HouseTypeId = 1 THEN 1 ELSE 0 END) AS "houseType1", 
     SUM(CASE WHEN HouseTypeId = 2 THEN 1 ELSE 0 END) AS "houseType2" 

Seine feine, tut es mir GROUP BY HouseTypeId zwingen.

Kann jemand erklären, warum das ist?

+0

Sie können dies in SQL Server grundsätzlich nicht tun. Um mit einer Variablenspalte zu arbeiten, benötigen Sie dynamisches SQL. Eine Funktion kann dynamisches SQL nicht problemlos ausführen. –

Antwort

2

Wenn Sie eine GROUP BY-Klausel verwenden, muss jede Spalte entweder in GROUP BY oder aggregiert sein. In Ihrem zweiten Beispiel erfüllen Sie diese Anforderungen - indem Sie SUM um den Funktionsaufruf platzieren. Da in Ihrem ersten Beispiel der Funktionsaufruf selbst nicht in eine Aggregation eingeschlossen ist (SUM, MAX, MIN usw.), müssen Sie ihn in die GROUP BY-Klausel einfügen, um keinen Fehler auszulösen.

https://msdn.microsoft.com/en-us/library/ms177673.aspx

ich mit Gordon einverstanden, obwohl, können Sie Ihre Strategie für diese zu überdenken wollen.

+0

Das ist die Antwort. Die SUM ist in der Funktion und nicht in der Hauptabfrage. –

+0

@ John Thompson, Dank John das macht viel Sinn und Punkt auf Ive überarbeitet meine Funktion nur die case-Anweisung verwenden und legte das Aggregat vor dem Funktionsaufruf. Funktioniert perfekt. –

0

Sie können nicht mit einer Funktion tun, was Sie wollen, da SQL Server in den Funktionen kein dynamisches SQL unterstützt. Und um irgendeine Spalte zu behandeln, würden Sie dynamisches SQL benötigen.

Aber Sie brauchen das sowieso nicht. Wenn Sie die Summe auf jeder Zeile der ursprünglichen Daten wollen, möchten Sie Fensterfunktionen:

SELECT SUM(CASE WHEN HouseTypeId = 1 THEN 1 ELSE 0 END) OVER() AS houseType1, 
     SUM(CASE WHEN HouseTypeId = 2 THEN 1 ELSE 0 END) OVER() AS houseType2 
. . . 

Aggregation wird für diese Abfrage nicht benötigt.

+0

Schauen Sie sich die Funktion genau an. Ich denke nicht, dass dies die Antwort ist. Er versucht nicht, dynamische SQL in einer Funktion zu tun. Er übergibt den Wert, nicht den Spaltennamen. Die Verwendung von '@ column' als Parametername ist trügerisch. –

+0

@Gordon Linoff Danke Gordon, das ist ein interessantes Thema. Johns Antwort hat mir geholfen, meine Funktion zu überarbeiten, so dass ich nicht durch HouseTypeId gruppieren muss. –

+0

@TabAlleman. . . Der Code sagt '@column = @ case' und das Beispiel scheint zu tun, was eine Windows-Funktion tut. –

Verwandte Themen