none
Ungereimtheit bei einer Common Table Expression (Schachbretträtsel) RRS feed

  • Frage

  • Hi,

    für das Nachstellen des Rätsels mit den Reiskörnern auf einem Schachbrett habe ich mal folgende CTE gebaut:

    ;WITH cte (k) AS
    (
    	SELECT
    		CAST(1 AS NUMERIC(38))
    	UNION ALL
    	SELECT
    		CAST(k * 2 AS NUMERIC(38))
    	FROM cte
    )
    SELECT
    	*
    FROM cte
    OPTION (MAXRECURSION 63)
    

    Hier erhalte ich zunächst folgenden Fehler:

    "Die Anweisung wurde beendet. Die maximale Rekursionstiefe 63 wurde vor Abschluss der Anweisung erreicht."

    Warum?

    Es wird jedoch ein passendes Resultset ausgegeben. Der 64. Wert zeigt die Anzahl der Reiskörner auf dem 64. Schachbrettfeld. Die Anzahl beträgt 9223372036854775808. Das ist korrekt. 2^64 via POWER(CAST(2 AS NUMERIC(38)), 64) im SQL ausgerechnet liefert den Wert 18446744073709552000. Warum gibt es hier eine Abweichung?

    Vielen Dank schon mal und viele Grüße

    Franz


    Donnerstag, 7. November 2019 11:11

Antworten

  • Warum gibt es hier eine Abweichung?

    Hallo Franz,

    ganz einfach: Zero-base => 2^0 = 1; die äquivalente Abfrage wäre also POWER(CAST(2 AS NUMERIC(38)), 63) um die 64ste Potenz zu erhalten.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]


    Donnerstag, 7. November 2019 11:58
  • Hallo Franz,

    Dir fehlt ein Abbruchkriterium!

    WITH cte (k, n) AS
    (
    	SELECT
    		CAST(1 AS NUMERIC(38)) as k, 1 as n
    	UNION ALL
    	SELECT
    		CAST(k * 2 AS NUMERIC(38)), n + 1
    	FROM cte
    	where n < 64
    )
    SELECT n as Rekursionstiefe, k	
    FROM cte
    OPTION (MAXRECURSION 63);
    Dann muss MAXRECURSION nur noch >= 63 sein!


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

    Donnerstag, 7. November 2019 12:30

Alle Antworten

  • Warum gibt es hier eine Abweichung?

    Hallo Franz,

    ganz einfach: Zero-base => 2^0 = 1; die äquivalente Abfrage wäre also POWER(CAST(2 AS NUMERIC(38)), 63) um die 64ste Potenz zu erhalten.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]


    Donnerstag, 7. November 2019 11:58
  • http://www.martinroedel.de/25er/maerchen.htm

    Richtig wäre also hier als Summe 2^64 - 1, da die Summe aller Reiskörner gefordert wurde.

    Donnerstag, 7. November 2019 12:04
  • Hallo Franz,

    Dir fehlt ein Abbruchkriterium!

    WITH cte (k, n) AS
    (
    	SELECT
    		CAST(1 AS NUMERIC(38)) as k, 1 as n
    	UNION ALL
    	SELECT
    		CAST(k * 2 AS NUMERIC(38)), n + 1
    	FROM cte
    	where n < 64
    )
    SELECT n as Rekursionstiefe, k	
    FROM cte
    OPTION (MAXRECURSION 63);
    Dann muss MAXRECURSION nur noch >= 63 sein!


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

    Donnerstag, 7. November 2019 12:30