none
Print ausgabe einer Variable übergeben RRS feed

  • Frage

  • Hallo an alle,

    leider ist mir kein besserer Titel eingefallen aber vielleicht zeigt er ja doch auf was für ein Vorhaben ich habe. Ziel ist es mit einer While und If Schleife mir eine SQL Statement selber zu erstellen.

    declare @Monat int =2
    declare @Jahr int =2012
    declare @Tag_anzahl int =28 
    declare @test int=0
    declare @i int = 0
    declare @SQL nvarchar(4000)
    
    --SET @SQL=()
    while @i <= @Tag_anzahl
    	Begin
    		
    		if  @i <@Tag_anzahl
    			Begin
    				PRINT @i 
    				PRINT 'as Tag union select' 	
    				SET @i=@i+1
    			END
    		
    		else if @i = @Tag_anzahl
    			
    			Begin
    				PRINT @i
    				PRINT  'as Tag' 
    				SET @i=@i+1
    			END
    		
    	END
    Die Ausgabe klappt aber wie bekomme ich das nun eine Variable oder wie bekomme ich das Aufgerufen? So das am Ende auch wirklich das Select abgesetzt wird und ich mit dem Ergebnis weiterarbeiten kann? Oder wie heißt die Technik die ich einsetzen muss damit ich mich bei Datenkrake und Co umschauen kann?
    Mittwoch, 25. März 2015 08:14

Antworten

  • Das geht ganz einfach. Hier nur der letzte Teil des Statements:

    With ...
    Select n1.n as Tag, n2.Stunde
    from Numbers n1
    cross join (Select n as Stunde
    from Numbers
    where n <= 24) as n2
    where n <= 28
    order by Tag, Stunde;

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

    Mittwoch, 25. März 2015 14:26
    Beantworter

Alle Antworten

  • Das finde ich viel zu kompliziert. Schau Dir mal das hier an:

    with
    t0(n) as
         (
         select 1
                 union all                                                -- Erzeugt zwei Sätze = 2^1
         select 1
         ),
    t1(n) as
         (
         select 1                                                        -- Cross Join erzeugt 4 Sätze = 2^2
         from        t0 as a,
                         t0 as b
         ),
    t2(n) as
         (
         select 1                                                        -- Cross Join erzeugt 16 Sätze = 2^4
         from        t1 as a,
                         t1 as b
         ),
    t3(n) as
         (
         select 1                                                        -- Cross Join erzeugt 256 Sätze = 
    2^8
         from        t2 as a,
                         t2 as b
         ),
    Numbers(n) as
         (
         Select row_number() over (order by n) as n
         from t3
         )
    Select n as Tag
    from Numbers
    where n <= 28;

    Durch entsprechende Ergänzungen kannst du das sehr schnell erweitern. Packe es dann noch in eine User Defined Function und Dir stehen alle Möglichkeiten offen.

    --
    -- Ändere das letzte Select so ab, dass die Werte von 1000 bis 1099 ausgeben 
    werden
    --
    with
    t0(n) as
         (
         select 1
                 union all                                                -- Erzeugt zwei Sätze = 2^1
         select 1
         ),
    t1(n) as
         (
         select 1                                                        -- Cross Join erzeugt 4 Sätze = 2^2
         from        t0 as a,
                         t0 as b
         ),
    t2(n) as
         (
         select 1                                                        -- Cross Join erzeugt 16 Sätze = 2^4
         from        t1 as a,
                         t1 as b
         ),
    t3(n) as
         (
         select 1                                                        -- Cross Join erzeugt 256 Sätze = 
    2^8
         from        t2 as a,
                         t2 as b
         ),
    Numbers(n) as
         (
         Select row_number() over (order by n) as n
         from t3
         )
    Select 1000 + n - 1 as n
    from Numbers
    where    n <= 1099 - 1000 + 1 ;
    
    -----------------------------------------------------------------------------------------------------------------------------------------------
     --
    -- Create Function muss die einzige Anweisung im Batch sein
    --
    go
    --
    -- Erzeuge eine Funktion "udf_Numbers", welche das eben erstellte Statement 
    verwendet
    -- In der Beispiellösung sind die CTE bis auf 2^32 Sätze erweitert
    -- Ersetze 1000 mit @from und @1099 mit @to
    --
    -- Schemabinding ist hier eigentlich überflüssig, aber eine sonst sinnvolle 
    Sicherheitsmassnahme.
    -- CREATE FUNCTION unterstützt eine SCHEMABINDING-Klausel, die die Funktion 
    an das Schema von Objekten bindet, auf die verwiesen wird,
    -- wie z. B. Tabellen, Sichten und andere benutzerdefinierte Funktionen. Der 
    Versuch, ein Objekt zu ändern oder zu löschen, auf das
    -- von einer schemagebundenen Funktion verwiesen wird, erzeugt einen Fehler.
    --
    create function udf_Numbers
    (
     @from as bigint,
     @to as bigint
    )
    returns table with schemabinding
    as
    return
         with
         t0(n) as
                 (
                 select 1
                         union all                                                -- Erzeugt zwei Sätze = 2^1
                 select 1
                 ),
         t1(n) as
                 (
                 select 1                                                        -- Cross Join erzeugt 4 Sätze = 
    2^2
                 from        t0 as a,
                                 t0 as b
                 ),
         t2(n) as
                 (
                 select 1                                                        -- Cross Join erzeugt 16 Sätze = 
    2^4
                 from        t1 as a,
                                 t1 as b
                 ),
         t3(n) as
                 (
                 select 1                                                        -- Cross Join erzeugt 256 Sätze 
    = 2^8
                 from        t2 as a,
                                 t2 as b
                 ),
         t4(n) as
                 (
                 select 1
                 from t3 as a, t3 as b                                -- Cross Join erzeugt 65.536 
    Sätze = 2^16
                 ),
         t5(n) as
                 (
                 select 1 from t4 as a, t4 as b                -- Cross Join erzeugt 
    4.294.967.296 Sätze = 2^32
                 ),
         Numbers(n) as                                                        -- nummeriert die Sätze durch 
    beginnend bei 1
                 (
                 select row_number() over (order by n) as n
                 from t5
                 )
         select @from + n - 1 as n                        -- addiert die laufende Nummer auf 
    den Startwert
         from Numbers
         where n <= @to - @from + 1                        -- so lange die Anzahl der Zeilen 
    eingehalten wird
    go
    
    -----------------------------------------------------------------------------------------------------------------------------------------------
    
    -- Teste die Funktion mit verschiedenen Werten
    --
    select *
    from udf_Numbers(1,101);
    
    --
    -- Erzeuge mir die Daten für 90 Tage ab Startdatum 01.01.2013
    --
    select dateadd(dd,n,'20130101') as Kalender
    from udf_Numbers(0,89);
     --
    -- Erzeuge mir die Daten für die Tage 10..90 ab Startdatum 01.01.2013
    --
    select dateadd(dd,n,'20130101') as Kalender
    from dbo.udf_Numbers(10,90);

    Das Original ist von Steve Kass.

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

    Mittwoch, 25. März 2015 08:42
    Beantworter
  • Hallo Christoph das Skript ist klasse (da wäre ich im Leben nicht drauf gekommen) jedoch lässt sich dies doch leider nicht vereinbaren mit meinen weiteren plänen. Oder bekommt man es hin das man auch die Uhrzeit in voller Stunde in einer weiteren Tabelle abgebildet bekommt?

    zb.

    Tag volle_Stunde

    1       1

    1        2

    1        3

    .

    .

    .

    31       23

    Mittwoch, 25. März 2015 14:14
  • Das geht ganz einfach. Hier nur der letzte Teil des Statements:

    With ...
    Select n1.n as Tag, n2.Stunde
    from Numbers n1
    cross join (Select n as Stunde
    from Numbers
    where n <= 24) as n2
    where n <= 28
    order by Tag, Stunde;

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

    Mittwoch, 25. März 2015 14:26
    Beantworter
  • Danke dir! das erspart mir ne menge Arbeit!
    Mittwoch, 25. März 2015 14:48
  • Hallo Christoph leider habe ich jetzt erfahren das nun die Zeit doch von 0 Uhr gemessen wird.

    Soll heißen es müsste nun so aussehen

    Tag volleStunde

    1       0

    1       1

    .

    .

    .

    31    23

    leider geht das mit deinem Skript nicht da er ja immer "erst" ab der 1.sten vollen Stunde anzeigt. Hast du vielleicht noch eine andere Lösung?

    Freitag, 27. März 2015 08:13
  • Hallo! Hier ist ein klein bisschen Kreativität gefragt. Wieder nur ein Teil des Statements:

    cross join (Select n-1 as Stunde

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

    Freitag, 27. März 2015 08:28
    Beantworter
  • ja klar ich zieh einfach 1 ab! manchmal sieht man den Wald vor lauter Bäumen nicht! danke dir!
    Freitag, 27. März 2015 08:52