none
Select innerhalb case end ? RRS feed

  • Frage

  • Hallo zusammen,

    ich habe mal wieder eine Frage :-)

    Wir haben eine Teilnehmer-Tabelle sowie eine Aktionstabelle aus der ich den aktuellsten Wert abfragen muss und zu der Aktion dann den entsprechenden Teilnehmer ausgeben möchte.

    Aber..
    In einere früheren (und fehlerhaften Programm-Version) wurde statt der GUID die Teilnehmer-eMail-Adresse eingetragen.

    Nun möchte ich beim Abfragen feststellen ob ein @ enthalten ist und dann den einen oder anderen Select absetzen, denke das ist der einfachste Wert, es sein denn das man auch auf eine GUID prüfen kann.

    Ich wollte das dann über einen Case/End Block machen, aber ich habe das nicht so recht verstanden :-)

    Versucht habe ich zuletzt folgendes:

    select top 1 
      case
        when charindex(N'@', a.ActionUser) = 0
          then (select a.LastDate, b.LastName, b.FirstName, b.eMail from dbo.History a, Member b where b.MemID = a.ActionUser)
          else (select a.LastDate, 'unknown', 'unknown', a.ActionUser from dbo.History a)
      end
    from dbo.History a, dbo.Member b order by a.ActionUser Desc

    Das klappt soweit nicht wie gedacht, nur wie macht man sowas richtig?

    Viele Grüsse,
    Maximilian

    Dienstag, 30. Juli 2013 12:33

Antworten

  • Hallo Maximilian,

    ein CASE Ausdruck kann immer nur einen skalaren Wert zurückgeben, nicht eine komplette Feldliste, insfoern vergleichbar mit IIF in Visual Basic.

    Und so würde sich aus dem Pseudo-SQL mit etwas Interpretation etwas ab wie:

    Zum einen weitgehend wörtlich übersetzt

    SELECT TOP(1)
    	a.LastDate,
    	CASE WHEN charindex(N'@', a.ActionUser) = 0
    		 THEN (SELECT b.LastName FROM dbo.Member AS b WHERE b.MemID = a.ActionUser)
    		 ELSE 'unknown' END,
    		 
    	CASE WHEN charindex(N'@', a.ActionUser) = 0
    		 THEN (SELECT b.FirstName FROM dbo.Member AS b WHERE b.MemID = a.ActionUser)
    		 ELSE 'unknown' END,
    		 
    	CASE WHEN charindex(N'@', a.ActionUser) = 0
    		THEN (SELECT b.eMail FROM dbo.Member AS b WHERE b.MemID = a.ActionUser)
    		ELSE a.ActionUser END
    FROM dbo.History AS a
    ORDER BY a.ActionUser DESC;

    oder mehr dem Sinne nach:

    SELECT TOP(1) a.LastDate, CASE WHEN charindex(N'@', a.ActionUser) = 0 THEN b.LastName ELSE 'unknown' END, CASE WHEN charindex(N'@', a.ActionUser) = 0 THEN b.FirstName ELSE 'unknown' END, CASE WHEN charindex(N'@', a.ActionUser) = 0 THEN b.eMail ELSE a.ActionUser END FROM dbo.History AS a -- evtl. INNER JOIN LEFT JOIN dbo.Member AS b ON b.MemID = a.ActionUser ORDER BY a.ActionUser DESC;

    wobei letzteres vorzuziehen wäre.
    Und je nachdem ob ein Member immer zur History existiert ist auch ein INNER JOIN infrage käme.

    Passt weder noch, bräuchte man mehr Informationen zur Tabellen- und Datenstruktur.

    Gruß Elmar


    • Bearbeitet Elmar Boye Dienstag, 30. Juli 2013 16:15 TOP(1)
    • Als Antwort markiert MaxiTesch Mittwoch, 31. Juli 2013 04:28
    Dienstag, 30. Juli 2013 16:13
  • Hallo Maximilian,

    den CASE Ausdruck musst Du insgesamt betrachten. Die Variablenzuweisung wird bei jedem Ausdruck davor geschieben: @Variable = CASE WHEN ... END. Für oben:

    EXEC sp_executesql 'SELECT TOP(1) '
    + '	@LasteDate = a.LastDate, '
    + '	@LsstName = CASE WHEN charindex(N'@', a.ActionUser) = 0 '
    + '		 THEN b.LastName '
    + '		 ELSE 'unknown' END, '
    + '	@FirstName = CASE WHEN charindex(N'@', a.ActionUser) = 0 '
    + '		 THEN b.FirstName
    + '		 ELSE 'unknown' END,
    + '	@ActionUser = CASE WHEN charindex(N'@', a.ActionUser) = 0 '
    + '		THEN b.eMail '
    + '		ELSE a.ActionUser END '
    + 'FROM dbo.History AS a '
    + 'LEFT JOIN dbo.Member AS b ON b.MemID = a.ActionUser '
    + 'ORDER BY a.ActionUser DESC;'.
    N'@LastDate datetime OUT, @LastName nvarchar(40) OUT, @FirstName nvarchar(40) OUT, @ActionUser nvarchar(40) OUT',
    @LastDete OUT, @LastName OUT, @FirstName OUT, @ActionUser OUT;
    Gruß Elmar

    • Als Antwort markiert MaxiTesch Donnerstag, 8. August 2013 04:08
    Mittwoch, 31. Juli 2013 07:51

Alle Antworten

  • Hallo Maximilian,

    ein CASE Ausdruck kann immer nur einen skalaren Wert zurückgeben, nicht eine komplette Feldliste, insfoern vergleichbar mit IIF in Visual Basic.

    Und so würde sich aus dem Pseudo-SQL mit etwas Interpretation etwas ab wie:

    Zum einen weitgehend wörtlich übersetzt

    SELECT TOP(1)
    	a.LastDate,
    	CASE WHEN charindex(N'@', a.ActionUser) = 0
    		 THEN (SELECT b.LastName FROM dbo.Member AS b WHERE b.MemID = a.ActionUser)
    		 ELSE 'unknown' END,
    		 
    	CASE WHEN charindex(N'@', a.ActionUser) = 0
    		 THEN (SELECT b.FirstName FROM dbo.Member AS b WHERE b.MemID = a.ActionUser)
    		 ELSE 'unknown' END,
    		 
    	CASE WHEN charindex(N'@', a.ActionUser) = 0
    		THEN (SELECT b.eMail FROM dbo.Member AS b WHERE b.MemID = a.ActionUser)
    		ELSE a.ActionUser END
    FROM dbo.History AS a
    ORDER BY a.ActionUser DESC;

    oder mehr dem Sinne nach:

    SELECT TOP(1) a.LastDate, CASE WHEN charindex(N'@', a.ActionUser) = 0 THEN b.LastName ELSE 'unknown' END, CASE WHEN charindex(N'@', a.ActionUser) = 0 THEN b.FirstName ELSE 'unknown' END, CASE WHEN charindex(N'@', a.ActionUser) = 0 THEN b.eMail ELSE a.ActionUser END FROM dbo.History AS a -- evtl. INNER JOIN LEFT JOIN dbo.Member AS b ON b.MemID = a.ActionUser ORDER BY a.ActionUser DESC;

    wobei letzteres vorzuziehen wäre.
    Und je nachdem ob ein Member immer zur History existiert ist auch ein INNER JOIN infrage käme.

    Passt weder noch, bräuchte man mehr Informationen zur Tabellen- und Datenstruktur.

    Gruß Elmar


    • Bearbeitet Elmar Boye Dienstag, 30. Juli 2013 16:15 TOP(1)
    • Als Antwort markiert MaxiTesch Mittwoch, 31. Juli 2013 04:28
    Dienstag, 30. Juli 2013 16:13
  • Hallo Elmar,

    tausend Dank für Deine Info, ich muss noch viel lernen...

    Als der erste Test per Text-Ausgabe geklappt hat, habe ich mich darauf versteift auf dem richtigen Weg zu sein, aber war halt eben auf dem Holzweg.

    Nochmals vielen Dank,
    Maximilien

    Mittwoch, 31. Juli 2013 04:28
  • Hallo Elmar,

    ich muss nochmal kurz zurück kommen, ich habe eine weitere Frage...

    Vieleicht habe ich falsch angefangen, ich teste erst an einer Datenbank ob alles klappt und schreibe dann dynamisches SQL weil ich die DB's in einem Cursor durchgehe und Use ja leider nicht funktioniert.

    Wie kann ich die zweite Abfrage über sp_executesql machen und die Angaben als OUTPUT bekommen? Leider klappt es nicht wenn ich z.Bsp. für b.LastName im dynamischen SQL-Statement schreibe "CASE WHEN... THEN @LastNameOUT = b.LastName" um dann die Werte zu bekommen.

    Sorry wenn ich nochmal nachfrage, aber bei meinem Versuch das umzusetzen meckert SQL, dürfte so also nicht gehen.

    Bin gerade am überlegen statt dessen ein UPDATE #tabelle SET [LastName] = ... WHERE [ID] = ... zu versuchen, denke aber das wird dann auch nicht klappen.

    Viele Grüsse,
    Maximilian

    Mittwoch, 31. Juli 2013 06:20
  • Hallo Maximilian,

    den CASE Ausdruck musst Du insgesamt betrachten. Die Variablenzuweisung wird bei jedem Ausdruck davor geschieben: @Variable = CASE WHEN ... END. Für oben:

    EXEC sp_executesql 'SELECT TOP(1) '
    + '	@LasteDate = a.LastDate, '
    + '	@LsstName = CASE WHEN charindex(N'@', a.ActionUser) = 0 '
    + '		 THEN b.LastName '
    + '		 ELSE 'unknown' END, '
    + '	@FirstName = CASE WHEN charindex(N'@', a.ActionUser) = 0 '
    + '		 THEN b.FirstName
    + '		 ELSE 'unknown' END,
    + '	@ActionUser = CASE WHEN charindex(N'@', a.ActionUser) = 0 '
    + '		THEN b.eMail '
    + '		ELSE a.ActionUser END '
    + 'FROM dbo.History AS a '
    + 'LEFT JOIN dbo.Member AS b ON b.MemID = a.ActionUser '
    + 'ORDER BY a.ActionUser DESC;'.
    N'@LastDate datetime OUT, @LastName nvarchar(40) OUT, @FirstName nvarchar(40) OUT, @ActionUser nvarchar(40) OUT',
    @LastDete OUT, @LastName OUT, @FirstName OUT, @ActionUser OUT;
    Gruß Elmar

    • Als Antwort markiert MaxiTesch Donnerstag, 8. August 2013 04:08
    Mittwoch, 31. Juli 2013 07:51
  • Hallo Elmar,

    tausend Dank, klappt besten :-)

    Gruss,
    Maximilian

    Donnerstag, 8. August 2013 04:09