none
Problem mit COUNT(*) RRS feed

  • Frage

  • Hallo, ich habe folgende Abfrage:

    SELECT
        COUNT(*) as Anzahl,
        DATENAME(HOUR,POS.dbo.transaction.date) AS Stunde,
        DATENAME(weekday , POS.dbo.transaction.date) AS Wochentag
    
    FROM POS.dbo.transaction_line_item AS TLI
             LEFT JOIN POS.dbo.transaction ON TLI.fk_transaction = POS.dbo.transaction.transaction_id
    WHERE POS.dbo.transaction.fk_status <> '3'
    
    GROUP BY DATENAME(weekday , POS.dbo.transaction.date),
             DATENAME(HOUR,POS.dbo.transaction.date)
    ORDER BY Wochentag,
             Stunde

    Das produziert mir eine Ausgabe mit den Spalten Anzahl, Stunde und Wochentag. Soweit so gut.

    Jetzt möchte ich jedoch Beispielhaft, dass nur die Tage berücksichtigt werden, an denen die Anzahl während der Stunde 9 zwischen '0' und '10' liegt.

    Da komme ich einfach nicht weiter....laufe auf Grund und bin am schleudern!!!

    Montag, 10. August 2020 13:54

Antworten

  • Ich denke, damit sieht man dann nur noch die Stunde 9, aber nicht mehr den ganzen Tag.

    WITH Special_Days AS
    (   SELECT
            POS.dbo.transaction.date as MyDate
        FROM POS.dbo.transaction_line_item AS TLI
                 LEFT JOIN POS.dbo.transaction ON TLI.fk_transaction = POS.dbo.transaction.transaction_id
        WHERE POS.dbo.transaction.fk_status <> '3'
    	AND DATENAME(HOUR,POS.dbo.transaction.date) = 9
    	GROUP BY DATENAME(weekday , POS.dbo.transaction.date)
    	HAVING Count(*) BETWEEN 0 AND 10
    )
    SELECT
            COUNT(*) as Anzahl,
            DATENAME(HOUR,POS.dbo.transaction.date) AS Stunde,
            DATENAME(weekday , POS.dbo.transaction.date) AS Wochentag
    
        FROM POS.dbo.transaction_line_item AS TLI
                 LEFT JOIN POS.dbo.transaction ON TLI.fk_transaction = POS.dbo.transaction.transaction_id
        WHERE POS.dbo.transaction.fk_status <> '3'
    	and POS.dbo.transaction.date in (SELECT MyDate FROM Special_Days)
    
        GROUP BY DATENAME(weekday , POS.dbo.transaction.date),
                 DATENAME(HOUR,POS.dbo.transaction.date)
    ;

    Es könnte also wohl so gehen, was ich aber nicht getestet habe!
    Insbesondere die Bedingung mit Count=0 ist interessant, da es hier wohl eher keinen Satz gibt, wenn man die Stunden nicht außerdem mit einer Tabelle mit den Zahlen 1..24 vereinigt. 

    Dazu ein Beispiel mit einer kleinen rekursiven Nummern-CTE:

    CREATE TABLE #test(tag datetime);
    
    INSERT INTO #test values('2020-08-11 08:00:00'),('2020-08-11 09:00:00'),('2020-08-11 09:00:00');
    
    WITH MyNumbers(n) AS 
    (
    	SELECT 0 AS n
    	UNION ALL
    	SELECT n+1 
    	FROM MyNumbers 
    	WHERE n <23
    ), MyDay AS 
    (
    SELECT DATENAME(hour, t.tag) AS MyHour, count(*) AS Count_Day
    FROM #test t
    GROUP BY DATENAME(hour, t.tag)
    )
    SELECT m.n, coalesce(d.Count_Day, 0) AS Anzahl
    FROM MyNumbers m 
    LEFT Join MyDay d
    	ON m.n = d.MyHour
    Order BY m.n;
    
    go
    DROP TABLE #test;

    HTH!


    Einen schönen Tag noch, Christoph - http://www.insidesql.org/blogs/cmu

    Dienstag, 11. August 2020 06:02
  • Du kannst in dem Count auch einen Ausdruck angeben, der nur das berücksichtigt was der Bedingung entspricht:

    count(case DATENAME(HOUR,POS.dbo.transaction.date) when 9 then 1 else null end)

    Ansonsten kann man eine "Having"-Klausel nach einer Group by Klausel auf die Ergebnisse anwenden, was diese natürlich einschränkt:

    group by ...
    having  DATENAME(HOUR,POS.dbo.transaction.date) = 9 and count(*) between 0 and 10

    Dienstag, 11. August 2020 09:11

Alle Antworten

  • Hi,

    poste bitte die Tabellen als CREATE TABLE Statements, Beispieldaten als INSERT INTO Statements und - basierend auf genau diesen Beispieldaten - das gewünschte Ergebnis.

    Dann schauen wir mal weiter.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Montag, 10. August 2020 14:11
    Moderator
  • Hallo LeGrandLuc,

    versuche es mal damit:

    SELECT *
    FROM (
        SELECT
            COUNT(*) as Anzahl,
            DATENAME(HOUR,POS.dbo.transaction.date) AS Stunde,
            DATENAME(weekday , POS.dbo.transaction.date) AS Wochentag
    
        FROM POS.dbo.transaction_line_item AS TLI
                 LEFT JOIN POS.dbo.transaction ON TLI.fk_transaction = POS.dbo.transaction.transaction_id
        WHERE POS.dbo.transaction.fk_status <> '3'
    
        GROUP BY DATENAME(weekday , POS.dbo.transaction.date),
                 DATENAME(HOUR,POS.dbo.transaction.date)
    ) AS t1
    
    WHERE stunde = 9
        AND Anzahl BETWEEN 0 AND 10
    
    ORDER BY Wochentag,
             Stunde
    Schönen Abend.

    Montag, 10. August 2020 18:19
  • Ich denke, damit sieht man dann nur noch die Stunde 9, aber nicht mehr den ganzen Tag.

    WITH Special_Days AS
    (   SELECT
            POS.dbo.transaction.date as MyDate
        FROM POS.dbo.transaction_line_item AS TLI
                 LEFT JOIN POS.dbo.transaction ON TLI.fk_transaction = POS.dbo.transaction.transaction_id
        WHERE POS.dbo.transaction.fk_status <> '3'
    	AND DATENAME(HOUR,POS.dbo.transaction.date) = 9
    	GROUP BY DATENAME(weekday , POS.dbo.transaction.date)
    	HAVING Count(*) BETWEEN 0 AND 10
    )
    SELECT
            COUNT(*) as Anzahl,
            DATENAME(HOUR,POS.dbo.transaction.date) AS Stunde,
            DATENAME(weekday , POS.dbo.transaction.date) AS Wochentag
    
        FROM POS.dbo.transaction_line_item AS TLI
                 LEFT JOIN POS.dbo.transaction ON TLI.fk_transaction = POS.dbo.transaction.transaction_id
        WHERE POS.dbo.transaction.fk_status <> '3'
    	and POS.dbo.transaction.date in (SELECT MyDate FROM Special_Days)
    
        GROUP BY DATENAME(weekday , POS.dbo.transaction.date),
                 DATENAME(HOUR,POS.dbo.transaction.date)
    ;

    Es könnte also wohl so gehen, was ich aber nicht getestet habe!
    Insbesondere die Bedingung mit Count=0 ist interessant, da es hier wohl eher keinen Satz gibt, wenn man die Stunden nicht außerdem mit einer Tabelle mit den Zahlen 1..24 vereinigt. 

    Dazu ein Beispiel mit einer kleinen rekursiven Nummern-CTE:

    CREATE TABLE #test(tag datetime);
    
    INSERT INTO #test values('2020-08-11 08:00:00'),('2020-08-11 09:00:00'),('2020-08-11 09:00:00');
    
    WITH MyNumbers(n) AS 
    (
    	SELECT 0 AS n
    	UNION ALL
    	SELECT n+1 
    	FROM MyNumbers 
    	WHERE n <23
    ), MyDay AS 
    (
    SELECT DATENAME(hour, t.tag) AS MyHour, count(*) AS Count_Day
    FROM #test t
    GROUP BY DATENAME(hour, t.tag)
    )
    SELECT m.n, coalesce(d.Count_Day, 0) AS Anzahl
    FROM MyNumbers m 
    LEFT Join MyDay d
    	ON m.n = d.MyHour
    Order BY m.n;
    
    go
    DROP TABLE #test;

    HTH!


    Einen schönen Tag noch, Christoph - http://www.insidesql.org/blogs/cmu

    Dienstag, 11. August 2020 06:02
  • Du kannst in dem Count auch einen Ausdruck angeben, der nur das berücksichtigt was der Bedingung entspricht:

    count(case DATENAME(HOUR,POS.dbo.transaction.date) when 9 then 1 else null end)

    Ansonsten kann man eine "Having"-Klausel nach einer Group by Klausel auf die Ergebnisse anwenden, was diese natürlich einschränkt:

    group by ...
    having  DATENAME(HOUR,POS.dbo.transaction.date) = 9 and count(*) between 0 and 10

    Dienstag, 11. August 2020 09:11