none
Suche nach SQL-Statement RRS feed

  • Frage

  • Bin auf der Suche nach einem SQL-Statement.

    Grundlage:
    Visual Studio Express 2013 für Windows Desktop
    ACCDB-Datenbank (eingebunden über Datenquelle)

    Ich habe zwei Tabellen:
    Tabelle1 mit Prüfungsfragen (jeder Datensatz hat einen eindeutigen IDX)
    Tabelle2 mit Prüfungsantworten je Teilnehmen (die zugehörige Frage wird als Prüfungsfragen-IDX eingetragen)

    Frage:
    Ich suche ein SQL-Statement (arbeite zur Zeit mit dem Abfrage-Editor), welches mir eine Liste der noch nicht beantworteten Fragen (aus Tabelle1) je Teilnehmer ausgibt.

    Danke vorab

    Ronald

    Samstag, 27. Dezember 2014 18:32

Antworten

  • Hallo Ronald,

    wenn Du alle bekommen willst, d. h. auch die Teilnehmer die noch gar nichts beantwortet haben, müsstest Du über drei Tabellen gehen. Siehe unten stehenden Beispiel - mit SQL Server erstellt, die Abfrage (ohne CROSS JOIN) sollte auch mit Access 20xx funktionieren:

    CREATE TABLE Fragen (
    	FrageID int NOT NULL 
    		CONSTRAINT PK_Fragen PRIMARY KEY,
    	Frage nvarchar(100) NOT NULL);
    
    CREATE TABLE Teilnehmer (
    	TeilnehmerID int NOT NULL 
    		CONSTRAINT PK_TeilnehmerID PRIMARY KEY,
    	Name nvarchar(50) NOT NULL);
    	
    CREATE TABLE Antworten (
    	AntwortenID int IDENTITY(1, 1) NOT NULL PRIMARY KEY,
    	TeilnehmerID int NOT NULL,
    	FrageID int NOT NULL,
    	Antwort int NOT NULL,
    	CONSTRAINT UK_Antworten UNIQUE (TeilnehmerID, FrageID));
    GO
    
    INSERT INTO Fragen (FrageID, Frage) VALUES
    	(1, N'Frage 1'),
    	(2, N'Frage 2'),
    	(3, N'Frage 3');
    
    INSERT INTO Teilnehmer (TeilnehmerID, Name) VALUES
    	(1001, N'Teilnehmer 1'),
    	(1002, N'Teilnehmer 2'),
    	(1003, N'Teilnehmer 3'),
    	(1004, N'Teilnehmer 4');
    
    INSERT INTO Antworten (TeilnehmerID, FrageID, Antwort) VALUES
    	(1001, 1, 1),
    	(1001, 2, 2),
    	(1001, 3, 3),
    	(1002, 2, 1),
    	(1002, 3, 3),
    	(1003, 1, 1);
    GO	
    SELECT * 
    FROM Teilnehmer, Fragen
    WHERE NOT EXISTS(SELECT * 
    	FROM Antworten 
    	WHERE Teilnehmer.TeilnehmerID = Antworten.TeilnehmerID
    		AND Fragen.FrageID = Antworten.FrageID)
    ORDER BY Teilnehmer.TeilnehmerID, Fragen.FrageID;
    
    -- oder (ANSI 92 CROSS JOIN)
    SELECT * 
    FROM Teilnehmer
    CROSS JOIN Fragen
    WHERE NOT EXISTS(SELECT * 
    	FROM Antworten 
    	WHERE Teilnehmer.TeilnehmerID = Antworten.TeilnehmerID
    		AND Fragen.FrageID = Antworten.FrageID)
    ORDER BY Teilnehmer.TeilnehmerID, Fragen.FrageID;
    GO
    DROP TABLE Fragen, Teilnehmer, Antworten;
    GO
    

    (oben hat Teilnehmer 4 keine Antwort gegeben, 1 alle, 2 und 3 teile)

    Gruß Elmar

    Samstag, 27. Dezember 2014 19:50
    Beantworter
  • Hallo Ronald,

    generell ist es immer hilfreich, wenn Du sowohl die exakte Tabellenstruktur (wenn machbar, als CREATE TABLE Statements) sowie einige Beispieldatensätze (als INSERT INTO Statement) und das gewünschte Ergebnis postest.

    Um deine Frage zu beantworten, fehlt eigentlich aber eh noch die Teilnehmertabelle. Ich nehme an, diese existiert und ist in Tabelle2 mit den jeweiligen ID Werten verknüpft).

    In dem Fall würde ich es mal so probieren:

    SELECT f.ID AS IDFrage,
           a.ID AS IDAntwort,
           t.ID AS IDTeilnehmer
    FROM   Fragen f
            LEFT JOIN Antworten  a ON a.IDFrage      = f.ID
           RIGHT JOIN Teilnehmer t ON a.IDTeilnehmer = t.ID
    WHERE  a.IDFrage IS NULL
    

    Ob das bei dir nun überhaupt so machbar wäre, weiß ich nicht, da ich die Tabellenstrukutur nicht kenne. Poste daher bitte die fehlenden (o.g.) Informationen, dann kann ich das Beispiel ergänzen und/oder korrigieren.


    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, 27. Dezember 2014 19:51
    Moderator
  • Danke für alle Antworten

    Ich habe es allerdings anders gelöst.

    Habe mir eine DataGridView erstellt. Im ersten Durchlauf habe ich alle Fragen aus der Datenbank eingetragen. Im Zweiten Durchlauf habe ich in einer neuen Spalte - basierend auf einer SQL-Abfrage - eingetragen, ob der Kunde die Frage schon beantwortet hat. Diese Lösung hat für mich den Vorteil, dass ich mir zusätzliche Spalten mit Detailinformationen, Berechnungen und optische Hinweise einbauen konnte.

    Per CellClick kann ich mir jetzt zudem gezielt die Frage bzw deren Antwort ansehen.

    Danke für eure Bemühungen
    Ronald

    Dienstag, 30. Dezember 2014 22:48

Alle Antworten

  • Hallo Ronald,

    wenn Du alle bekommen willst, d. h. auch die Teilnehmer die noch gar nichts beantwortet haben, müsstest Du über drei Tabellen gehen. Siehe unten stehenden Beispiel - mit SQL Server erstellt, die Abfrage (ohne CROSS JOIN) sollte auch mit Access 20xx funktionieren:

    CREATE TABLE Fragen (
    	FrageID int NOT NULL 
    		CONSTRAINT PK_Fragen PRIMARY KEY,
    	Frage nvarchar(100) NOT NULL);
    
    CREATE TABLE Teilnehmer (
    	TeilnehmerID int NOT NULL 
    		CONSTRAINT PK_TeilnehmerID PRIMARY KEY,
    	Name nvarchar(50) NOT NULL);
    	
    CREATE TABLE Antworten (
    	AntwortenID int IDENTITY(1, 1) NOT NULL PRIMARY KEY,
    	TeilnehmerID int NOT NULL,
    	FrageID int NOT NULL,
    	Antwort int NOT NULL,
    	CONSTRAINT UK_Antworten UNIQUE (TeilnehmerID, FrageID));
    GO
    
    INSERT INTO Fragen (FrageID, Frage) VALUES
    	(1, N'Frage 1'),
    	(2, N'Frage 2'),
    	(3, N'Frage 3');
    
    INSERT INTO Teilnehmer (TeilnehmerID, Name) VALUES
    	(1001, N'Teilnehmer 1'),
    	(1002, N'Teilnehmer 2'),
    	(1003, N'Teilnehmer 3'),
    	(1004, N'Teilnehmer 4');
    
    INSERT INTO Antworten (TeilnehmerID, FrageID, Antwort) VALUES
    	(1001, 1, 1),
    	(1001, 2, 2),
    	(1001, 3, 3),
    	(1002, 2, 1),
    	(1002, 3, 3),
    	(1003, 1, 1);
    GO	
    SELECT * 
    FROM Teilnehmer, Fragen
    WHERE NOT EXISTS(SELECT * 
    	FROM Antworten 
    	WHERE Teilnehmer.TeilnehmerID = Antworten.TeilnehmerID
    		AND Fragen.FrageID = Antworten.FrageID)
    ORDER BY Teilnehmer.TeilnehmerID, Fragen.FrageID;
    
    -- oder (ANSI 92 CROSS JOIN)
    SELECT * 
    FROM Teilnehmer
    CROSS JOIN Fragen
    WHERE NOT EXISTS(SELECT * 
    	FROM Antworten 
    	WHERE Teilnehmer.TeilnehmerID = Antworten.TeilnehmerID
    		AND Fragen.FrageID = Antworten.FrageID)
    ORDER BY Teilnehmer.TeilnehmerID, Fragen.FrageID;
    GO
    DROP TABLE Fragen, Teilnehmer, Antworten;
    GO
    

    (oben hat Teilnehmer 4 keine Antwort gegeben, 1 alle, 2 und 3 teile)

    Gruß Elmar

    Samstag, 27. Dezember 2014 19:50
    Beantworter
  • Hallo Ronald,

    generell ist es immer hilfreich, wenn Du sowohl die exakte Tabellenstruktur (wenn machbar, als CREATE TABLE Statements) sowie einige Beispieldatensätze (als INSERT INTO Statement) und das gewünschte Ergebnis postest.

    Um deine Frage zu beantworten, fehlt eigentlich aber eh noch die Teilnehmertabelle. Ich nehme an, diese existiert und ist in Tabelle2 mit den jeweiligen ID Werten verknüpft).

    In dem Fall würde ich es mal so probieren:

    SELECT f.ID AS IDFrage,
           a.ID AS IDAntwort,
           t.ID AS IDTeilnehmer
    FROM   Fragen f
            LEFT JOIN Antworten  a ON a.IDFrage      = f.ID
           RIGHT JOIN Teilnehmer t ON a.IDTeilnehmer = t.ID
    WHERE  a.IDFrage IS NULL
    

    Ob das bei dir nun überhaupt so machbar wäre, weiß ich nicht, da ich die Tabellenstrukutur nicht kenne. Poste daher bitte die fehlenden (o.g.) Informationen, dann kann ich das Beispiel ergänzen und/oder korrigieren.


    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, 27. Dezember 2014 19:51
    Moderator
  • Hallo Stefan

    Anbei die Informationen wie gewünscht.

    Tabelle1 (Antworten):
    ID (IDX), ID_Kunde, ID_Skill, Ergebnis

    Tabelle2 (Fragen):
    ID (IDX), Frage, Beschreibung

    Jede Frage kann 1:n Antworten haben.

    Ich will lediglich die unbeantworteten Fragen je Kunden wissen.

    Danke vorab

    Ronald

    Samstag, 27. Dezember 2014 21:37
  • Hi Ronald,
    um zu wissen, welcher Kunde nicht vollständig geantwortet hat, benötigst Du für den Fall, dass ein Kunde keine Antwort abgegeben hat, eine Kundenliste (mit ID_Kunde). Es sind noch weitere Bedingungen erforderlich, z.B., ob jeder Kunde zu einer Frage nur eine oder mehrere Antworten abgegeben kann. Zur Übersichtlichkeit sollte die Fremdschlüsselspalte der Tabelle1 nicht auch ID genannt werden, da mit ID eigentlich ein eindeutiger Identifikator eines Datensatzes in der Tabelle angenommen wird, der für das Aktualisieren von Daten benötigt wird. Besser wäre als Benennung der Fremdschlüsselspalte ID_Frage.

    Wenn Du die Liste mit den Kunden hast und nur eine Antwort je Frage von einem Kunden zulässig ist, kannst Du mit Gruppierung je ID_Kunde und Count alle Kunden anzeigen lassen, bei denen die gefundene Anzahl nicht der Anzahl der Fragen entspricht. -> s. auch Elmars Beispiel.

    --
    Peter


    Sonntag, 28. Dezember 2014 12:51
  • Danke für alle Antworten

    Ich habe es allerdings anders gelöst.

    Habe mir eine DataGridView erstellt. Im ersten Durchlauf habe ich alle Fragen aus der Datenbank eingetragen. Im Zweiten Durchlauf habe ich in einer neuen Spalte - basierend auf einer SQL-Abfrage - eingetragen, ob der Kunde die Frage schon beantwortet hat. Diese Lösung hat für mich den Vorteil, dass ich mir zusätzliche Spalten mit Detailinformationen, Berechnungen und optische Hinweise einbauen konnte.

    Per CellClick kann ich mir jetzt zudem gezielt die Frage bzw deren Antwort ansehen.

    Danke für eure Bemühungen
    Ronald

    Dienstag, 30. Dezember 2014 22:48