none
was ist an meiner UNION-Abfrage falsch? RRS feed

  • Frage

  • Hallo,

    kann jemand mir vielleicht sagen, was an dieser UNION-Abfrage falsch ist?

    SELECT D.eltern, D.arbeitszeitWirklich FROM dbo.dienstart AS D WHERE (D.id = " + dienstart + ")
    UNION
    SELECT T.arbeitszeitDienstartID, T.GeaendertAZDienstart FROM dbo.benutzerTarif AS T WHERE ((T.zugeteiltAn = " + ownerKey + ") "
    AND (T.tarifBeginn <= CONVERT(DATETIME,'" + datum + "', 104)) AND
    CONVERT( DATETIME, '" + datum + "', 104 ) < (
    CASE
    WHEN T.tarifEnde IS NULL THEN '21991231'
    WHEN T.tarifEnde = '' THEN '21991231'
    ELSE T.tarifEnde
    END))"
    

     


    Gruesse, NUNUI

    Freitag, 3. Februar 2017 17:54

Antworten

  • Hi,

    nuja, wenn deine Tabellen gar nicht miteinander in Verbindung stehen, wie soll man dann wissen, welche Datensätze Du brauchst?

    Wenn eine dritte Tabelle involviert ist, muss man die Verbindung halt über drei Ebenen herstellen. Aber wie das in deinem Fall aussehen könnte, kann man nicht sagen, da man eben nicht weiß, wie deine Tabellen und deren Beziehungen aussehen.

    Falls es eine dritte Tabelle gibt, diese eine reine Beziehungstabelle zwischen D und T darstellt, stellt sich noch die Frage, wie die Beziehungen genau aussehen: 1:n, n:1, m:n, 1:1, ...?

    So oder so befürchte ich, dass Du da erheblich mehr Probleme hast als Du denkst. Bevor man solche Probleme löst, sollte man sich a) mit den Grundlagen von Datenbanken, deren Strukturen, usw. auskennen und natürlich die Basics von SQL kennen. Beides sehe ich bei dir derzeit nicht.

    Generell ist es natürlich nicht weiter schlimm, wenn man am Lernen ist. Aber ich habe so das Gefühl, dass jemand was von dir erwartet, was Du gar nicht leisten kannst!? Es würde mir helfen, wenn Du mit deinen Background ein wenig erklärst (Kenntnisstand, Aufgabenbereich hier, ...)

    ---

    Zum Thema selbst dann wieder:

    Um das Gewünschte machen zu können, muss es zwingend eine Verbindung (welcher Art auch immer) zwischen den beiden Tabellen geben. Ob das nun über eine dritte, vierte, fünfte, ... Tabelle passiert, ist erstmal egal. Wenn Du die Daten gezielt verbinden willst, brauchst Du eine Möglichkeit, das abzubilden.

    Poste daher bitte die Tabellenstrukturen der weiteren betroffenen Tabellen auch als CREATE TABLE Statements. Und bitte auch mal Beispieldaten und das gewünschte Ergebnis auf Basis dieser Beispieldaten!

    Hilfreich wäre auch ein Screenshot des Tabellendesigns inkl. der Beziehungen. Das kannst Du auch über das SSMS erzeugen, falls Du keins hast. Ein Beispiel hab ich mal als Grafik angehangen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    • Als Antwort markiert Nunui Sonntag, 5. Februar 2017 17:17
    Sonntag, 5. Februar 2017 12:01
    Moderator

Alle Antworten

  • Hi,

    wenn Du uns verraten würdest, was daran nicht läuft, welche Fehlermeldung Du erhältst oder welches Ergebnis Du erwarten würdest (falls es an sich läuft aber nicht die Ergebnisse bringt, Du du gerne hättest), können wir dir sicher auch sagen, was daran falsch ist.

    Falls es die Ergebnisse sind, poste bitte die CREATE TABLE Statements der betroffenen Tabellen, INSERT INTO Statements der Testdaten und das gewünschte Ergebnis auf Basis der Testdaten.

    Du solltest aber damit aufhören, Stringverkettungen zum Zusammenstellen von SQL Statements zu verwenden.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Freitag, 3. Februar 2017 18:49
    Moderator
  • Bekomme folgende Folgende Fehlermeldung:

    Der text-Datentyp kann nicht als Operand für den UNION-, INTERSECT- oder EXCEPT-Operator verwendet werden, da er nicht vergleichbar ist. "

    Glaube, dass es daran liegt, dass die Datentypen von zwei Select-Abfragen nicht zueinander passen!

    Was ich möchte, ist dass das Ergebnis von den zwei Select-Abfragen zusammen in einer Zeile auszugeben!


    Gruesse, NUNUI

    Freitag, 3. Februar 2017 22:38
  • Hi,

    wie dir IIRC schon (ggfs. sogar mehrfach) erklärt wurde, verwendet man für die Verbindung von Datensätzen mehrerer Tabellen zu einer gemeinsamen Zeile JOIN.

      Wie kann ich aus zwei Tabellen kombinierte Ausgaben machen?

    UNION verwendet man, wenn man die Datensätze mehrerer Abfragen in einem Resultset haben will.

    Da dir Olaf das mit JOIN schon erklärt hat, mach ich das nicht nochmal.

    BTW: Du solltest keine text oder ntext Spalten verwenden. Wenn Du wirklich so große Textinhalte speichern musst, nimm varchar( MAX ) oder nvarchar( MAX ).

    ---

    Ohne die in meiner ersten Antwort angefragten Infos (CREATE TABLE Statements, Beispieldaten als INSERT INTO, ...) können wir dir nur schwer helfen, daher poste die Sachen bitte, sollst ja schließlich auch was tun :)

    ---

    Einen kurzen aber guten Überblick in den Unterschied von JOIN und UNION findest Du bspw. hier:

      http://stackoverflow.com/questions/905379/what-is-the-difference-between-join-and-union

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Samstag, 4. Februar 2017 00:00
    Moderator
  • Hallo Stefan,

    Danke trotzdem für Deine Antwort.

    Ich habe auch erstmal mit JOIN, wie Olaf in einer andere Frage von mir erklärt hatte, versucht:

    SELECT D.eltern, D.arbeitszeitWirklich, T.arbeitszeitDienstartID, T.GeaendertAZDienstart 
    FROM dbo.dienstart AS D LEFT OUTER JOIN dbo.benutzerTarif AS T ON (D.id = " + dienstart + ") WHERE (
    (T.zugeteiltAn = " + ownerKey + ") AND (T.tarifBeginn <= CONVERT(DATETIME,'" + datum + "', 104)) AND 
    CONVERT( DATETIME, '" + datum + "', 104 ) < (
    CASE 
    WHEN T.tarifEnde IS NULL THEN '21991231' 
    WHEN T.tarifEnde = '' THEN '21991231' 
    ELSE T.tarifEnde "
    END))"
    

    Habe aber das Problem, dass sobald das Ergebnis für die Abfrage dbo.benutzerTarif leer ist, ist dann das Ergebnis für die gesamte Abfrage leer und das Ergebnis für die Abfrage dbo.dienstart wird nicht angezeigt!

    dbo.benutzerTarif:

    CREATE TABLE [dbo].[benutzerTarif](
    	[id] [int] IDENTITY(1,1) NOT NULL,
    	[tarifID] [int] NOT NULL,
    	[bezeichnung] [nvarchar](50) NULL,
    	[kurzel] [nvarchar](50) NULL,
    	[zugeteiltAn] [int] NOT NULL,
    	[erstelltVon] [int] NOT NULL,
    	[erstelltAm] [datetime] NOT NULL,
    	[aktuallisiertVon] [int] NULL,
    	[aktuallisiertAm] [datetime] NULL,
    	[tarifBeginn] [datetime] NOT NULL,
    	[tarifEnde] [datetime] NULL,
    	[wochenstunden] [float] NULL,
    	[tageWoche] [float] NULL,
    	[urlaubsanspruch] [float] NULL,
    	[ausgleichzeitraum] [varchar](20) NULL,
    	[freizeitausgleichDatum] [nvarchar](50) NULL,
    	[freizeitausgleichSF] [nvarchar](50) NULL,
    	[optOut] [bit] NULL,
    	[dienstartTyp] [int] NULL,
    	[beschfreieSonntageJahr] [smallint] NULL,
    	[beschfreieSonntageMonat] [tinyint] NULL,
    	[ueberstundenAusgleich] [bit] NULL,
    	[ueberstundenVerguetung] [bit] NULL,
    	[ruhezeitStunden] [nvarchar](50) NULL,
    	[ruhezeitWStunden] [nvarchar](50) NULL,
    	[termindifferenz] [float] NULL,
    	[bereitschaft] [nvarchar](50) NULL,
    	[rufbereitschaft] [nvarchar](50) NULL,
    	[nachtarbeitBeginn] [time](7) NULL,
    	[nachtarbeitEnde] [time](7) NULL,
    	[hoechstarbeitszeit] [nvarchar](50) NULL,
    	[spalten] [text] NULL,
    	[spaltenGeaendert] [text] NULL,
    	[arbeitszeitDienstartID] [text] NULL,
    	[GeaendertAZDienstart] [text] NULL,
    	[standort] [nvarchar](50) NULL,
    	[freigabe] [bit] NULL,
    	[restUrlaub] [varchar](10) NULL,
    	[restDienstart] [varchar](max) NULL,
    	[AbweichendeWocheStunden] [nvarchar](100) NULL,
    	[Feiertag_AZ] [bit] NULL DEFAULT ('False'),
    	[UrlaubArbeitszeit] [float] NULL CONSTRAINT [DF_benutzerTarif_UrlaubArbeitszeit]  DEFAULT ((12)),
     CONSTRAINT [PK_benutzerTarif] PRIMARY KEY CLUSTERED 
    (
    	[id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
    

    dbo.dienstart:

    CREATE TABLE [dbo].[dienstart](
    	[id] [int] IDENTITY(1,1) NOT NULL,
    	[dienstart] [nvarchar](50) NOT NULL,
    	[kuerzel] [nvarchar](50) NOT NULL,
    	[Monday] [smallint] NOT NULL,
    	[Tuesday] [smallint] NOT NULL,
    	[Wednesday] [smallint] NOT NULL,
    	[Thursday] [smallint] NOT NULL,
    	[Friday] [smallint] NOT NULL,
    	[Saturday] [smallint] NOT NULL,
    	[Sunday] [smallint] NOT NULL,
    	[Feiertag] [smallint] NOT NULL,
    	[uhrzeitAnfang] [time](7) NULL,
    	[uhrzeitEnde] [time](7) NULL,
    	[datumAnfang] [smalldatetime] NULL,
    	[datumEnde] [smalldatetime] NULL,
    	[farbe] [nvarchar](50) NULL,
    	[arbeitszeit] [smallint] NOT NULL,
    	[stundenzahl] [nvarchar](50) NULL,
    	[qualitaetHinzugefuegt] [nvarchar](max) NULL,
    	[gesamtuebersicht] [bit] NULL,
    	[eltern] [nvarchar](max) NULL,
    	[pflicht] [bit] NULL,
    	[dienstartTyp] [int] NULL,
    	[arbeitszeitWirklich] [float] NULL,
    	[standort] [nvarchar](50) NULL,
    	[freigabe] [bit] NULL,
    	[alternativ] [int] NULL,
    	[UntenAnzeigen] [bit] NULL,
     CONSTRAINT [PK_dienstart] PRIMARY KEY CLUSTERED 
    (
    	[id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]


    Gruesse, NUNUI

    Samstag, 4. Februar 2017 00:38
  • Hi,

    bitte noch einige Beispieldatensätze als INSERT INTO Statement(s) posten.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Samstag, 4. Februar 2017 10:57
    Moderator
  • Hi,

    nehmen wir dein Statement mal auseinander.

    SELECT D.eltern,
           D.arbeitszeitWirklich,
           T.arbeitszeitDienstartID,
           T.GeaendertAZDienstart 
    FROM   dienstart AS D
           LEFT OUTER JOIN benutzerTarif AS T ON D.id = " + dienstart + "
    WHERE  T.zugeteiltAn = " + ownerKey + "
    AND    T.tarifBeginn <= CONVERT( DATETIME, '" + datum + "', 104 )
    AND    CONVERT( DATETIME, '" + datum + "', 104 ) < CASE 
                                                           WHEN T.tarifEnde IS NULL THEN '21991231' 
                                                           WHEN T.tarifEnde = '' THEN '21991231' 
                                                           ELSE T.tarifEnde
                                                       END

    Was mit eingesetzten Werten bspw. dem hier entsprechen würde:

    SELECT D.eltern,
           D.arbeitszeitWirklich,
           T.arbeitszeitDienstartID,
           T.GeaendertAZDienstart 
    FROM   dienstart AS D
           LEFT OUTER JOIN benutzerTarif AS T ON D.id = 123
    WHERE  T.zugeteiltAn = 'Abc'
    AND    T.tarifBeginn <= CONVERT( DATETIME, '20170204', 104 )
    AND    CONVERT( DATETIME, '20170204', 104 ) < CASE 
                                                      WHEN T.tarifEnde IS NULL THEN '21991231' 
                                                      WHEN T.tarifEnde = '' THEN '21991231' 
                                                      ELSE T.tarifEnde
                                                  END

    Zum einen fehlt beim JOIN die Verbindung von D zu T.

    Dann fragst Du nach T.zugeteiltAn = 'Abc'. D.h., wenn es kein Ergebnis in T gibt, kommt gar kein Ergebnis raus.

    Dasselbe mit T.tarifBeginn.

    Zudem kann tarifEnde kein '' vorkommen. Des Weiteren sind tarifBeginn und tarifEnde datetime Spalten, d.h. es steht auch eine Zeitangabe drin. Wenn Du nur das Datum braucht, wäre es sinnvoller, "date" anstelle von "datetime" zu verwenden. Ob das problematisch ist, hängt aber von deinen Werten ab (also ob Uhrzeiten abweichend von 00:00:00 enthalten sind).

    ---

    Da ich nicht erkennen kann, wie deine beiden Tabellen überhaupt zueinander gehören sollen, nehme ich einfach mal an, dass die Spalte ID in "dienstart" mit der Spalte "arbeitszeitDienstartID" in "benutzerTarif" übereinstimmen müsste!?

    Falls dem so ist, könnte die Abfrage in etwa so korrekt sein (ist aber nur eine Vermutung, da deine Originalabfrage zumindest für mich keinerlei Sinn ergibt)

    SELECT D.eltern,
           D.arbeitszeitWirklich,
           T.arbeitszeitDienstartID,
           T.GeaendertAZDienstart 
    FROM   dienstart AS D
           LEFT OUTER JOIN benutzerTarif AS T ON D.id = t.arbeitszeitDienstartID
    WHERE  ISNULL( T.zugeteiltAn, 'Abc' )       = 'Abc'
    AND    ISNULL( T.tarifBeginn, '20170204' ) <= '20170204'
    AND    ISNULL( T.tarifEnde,   '21991231' ) <= '21991231'




    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    • Als Antwort markiert Nunui Sonntag, 5. Februar 2017 17:16
    • Tag als Antwort aufgehoben Nunui Sonntag, 5. Februar 2017 17:16
    Samstag, 4. Februar 2017 11:22
    Moderator
  • Hallo Stefan,

    entschuldige meine späte Antwort und auch Danke für die ausführliche Erklärung.
    Das Problem ist dass die beide Tabellen in keine Weise in Verbindung zueinander stehen.
    Die Abfrage wird beim Einfügen von neue Termine gemacht, nämlich bevor man den Termin einfügt, braucht man die definierte Arbeitszeit und die übergeordnete Dienste von dem Dienstart der dm Termin betrifft, die schon direkt im Dienstart definiert sind und dann die Zwei Werte aus dem Tarif haben eigentlich mit dem Dienstart nicht zu tun, sondern stehen in Verbindung mit einer anderen Tabelle.
    Aber um einen Termin für den Benutzer anlegen zu können, braucht man die Informationen aus der beiden Tabellen.
    Und jetzt weiss ich nicht wie ich das mit einer Abfrage machen kann?

    Gruesse, NUNUI

    Sonntag, 5. Februar 2017 11:06
  • Hi,

    nuja, wenn deine Tabellen gar nicht miteinander in Verbindung stehen, wie soll man dann wissen, welche Datensätze Du brauchst?

    Wenn eine dritte Tabelle involviert ist, muss man die Verbindung halt über drei Ebenen herstellen. Aber wie das in deinem Fall aussehen könnte, kann man nicht sagen, da man eben nicht weiß, wie deine Tabellen und deren Beziehungen aussehen.

    Falls es eine dritte Tabelle gibt, diese eine reine Beziehungstabelle zwischen D und T darstellt, stellt sich noch die Frage, wie die Beziehungen genau aussehen: 1:n, n:1, m:n, 1:1, ...?

    So oder so befürchte ich, dass Du da erheblich mehr Probleme hast als Du denkst. Bevor man solche Probleme löst, sollte man sich a) mit den Grundlagen von Datenbanken, deren Strukturen, usw. auskennen und natürlich die Basics von SQL kennen. Beides sehe ich bei dir derzeit nicht.

    Generell ist es natürlich nicht weiter schlimm, wenn man am Lernen ist. Aber ich habe so das Gefühl, dass jemand was von dir erwartet, was Du gar nicht leisten kannst!? Es würde mir helfen, wenn Du mit deinen Background ein wenig erklärst (Kenntnisstand, Aufgabenbereich hier, ...)

    ---

    Zum Thema selbst dann wieder:

    Um das Gewünschte machen zu können, muss es zwingend eine Verbindung (welcher Art auch immer) zwischen den beiden Tabellen geben. Ob das nun über eine dritte, vierte, fünfte, ... Tabelle passiert, ist erstmal egal. Wenn Du die Daten gezielt verbinden willst, brauchst Du eine Möglichkeit, das abzubilden.

    Poste daher bitte die Tabellenstrukturen der weiteren betroffenen Tabellen auch als CREATE TABLE Statements. Und bitte auch mal Beispieldaten und das gewünschte Ergebnis auf Basis dieser Beispieldaten!

    Hilfreich wäre auch ein Screenshot des Tabellendesigns inkl. der Beziehungen. Das kannst Du auch über das SSMS erzeugen, falls Du keins hast. Ein Beispiel hab ich mal als Grafik angehangen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    • Als Antwort markiert Nunui Sonntag, 5. Februar 2017 17:17
    Sonntag, 5. Februar 2017 12:01
    Moderator
  • Sagen wir, dass ich kein totaler Anfänger bin und kenne ich mich auch einigermaßen in der Materie aus :o)

    Es hat bis jetzt auch ohne Probleme funktioniert, weil die personalisierte Tarifdaten in Benutzertabelle gespeichert waren und deswegen konnte man auch auf jeden Fall über Benutzer an die erforderliche Informationen kommen.

    Jetzt wurden die Tarifdaten in einer Extratabelle ausgelagert, weil die Tarifdaten Datumsabhängig sein sollen.

    Es steht eigentlich die Tabelle benutzer in einer 1:n Relation zur Tabelle benutzerTarif.

    Danke für den Tip, daran habe ich gar nicht gedacht!!! Und jetzt funktioniert es wie erwünscht:

    SELECT D.eltern, D.arbeitszeitWirklich, 
    CASE WHEN T.arbeitszeitDienstartID IS NOT NULL THEN T.arbeitszeitDienstartID ELSE '' END AS arbeitszeitDienstartID,
    CASE WHEN T.GeaendertAZDienstart IS NOT NULL THEN T.GeaendertAZDienstart ELSE '' END AS GeaendertAZDienstart
    FROM dbo.dienstart AS D, dbo.benutzer AS B LEFT OUTER JOIN dbo.benutzerTarif AS T 
    ON ((B.id = 34) AND (B.id = T.zugeteiltAn) AND (T.tarifBeginn <= CONVERT(DATETIME, '20170204', 104)) AND 
    CONVERT( DATETIME, '20170204', 104 ) < (
    CASE 
    WHEN T.tarifEnde IS NULL THEN '21991231' 
    WHEN T.tarifEnde = '' THEN '21991231' 
    ELSE T.tarifEnde 
    END)) 
    WHERE ((D.id = 5) AND (B.id = 34))
    

    Danke!!!


    Gruesse, NUNUI

    Sonntag, 5. Februar 2017 17:15