2010-08-09 7 views
2

système: Windows7, Access 2003, fichier .mdb, langage C#, VS 2010MS Access - question de requêtes SQL

Je fais des requêtes avec OleDbCommand, donc j'écrire la requête SQL complète dans une chaîne.


Table Survey (Id) 
Table Questions (Id,IdSurvey) 
Table Answers (Id,IdQuestion) 

les tables sont simplifiées pour afficher uniquement les données pertinentes

On suppose 1 enquête a 1..n des questions
Assumer 1 question a des réponses 0..n

I Voulez-vous sélectionner uniquement les enquêtes qui ont les réponses 1 et/ou 2 pour la question 3, comment puis-je faire cela?

solution actuelle (et les pauvres):

SELECT surv.Name FROM Survey surv WHERE 
(1 IN (SELECT answ.Number FROM Answers answ, Questions quest 
WHERE quest.Id = 3 AND quest.IdSurvey = surv.Id) 
AND/OR 
(2 IN (SELECT answ.Number FROM Answers answ, Questions quest 
WHERE quest.Id = 3 AND quest.IdSurvey = surv.Id))) 

Cela ressemble à la merde, donc j'apprécierait l'aide.

Merci d'avance.


EDIT

Une meilleure solution que je suis venu avec:

Pour 1 OU 2, les solutions données ici sont assez (pour les expressions logiques très simples). Merci les gars

Pour 1 ET 2, j'ai créé une autre solution, semble un peu bien que je pense (encore une fois, pour les expressions logiques très simples)

SELECT surv.Name FROM Survey surv WHERE EXISTS 
(SELECT COUNT(*) FROM Answers answ, Questions quest 
WHERE quest.Id = 3 AND answ.Number IN (1,2) HAVING COUNT(*) > 1) 

Le "" dans le PRESENTANT La clause signifie qu'au moins deux lignes sont nécessaires, et puisque les réponses ne se répètent pas pour les mêmes questions, cela signifie nécessairement qu'au moins les réponses 1 ET 2 existent pour la question interrogée.

Eh bien, à la fois la OU solution et la ET solution sont mal lorsqu'ils traitent avec des expressions logiques plus complexes, comme (1 ET (2 OU (4 ET (6 ou 7)))), vérité Il est très improbable qu'une telle complexité soit nécessaire, mais j'aimerais être en sécurité. La solution idéale pour moi serait:

SELECT surv.Name FROM Survey surv WHERE 
(1 IN (SELECT answ.Number FROM Answers answ, Questions quest 
WHERE quest.Id = 3 AND quest.IdSurvey = surv.Id) AS CANT_DO_THIS 
AND/OR 
(2 IN CANT_DO_THIS) AND/OR 5 IN CANT_DO_THIS AND/OR 3 NOT IN CANT_DO_THIS) 

Répondre

0
SELECT surv.Name FROM Survery surv 
    INNER JOIN Questions quest ON surv.ID = quest.IDSurvey 
    INNER JOIN Answers answ ON quest.ID = answ.IDQuestion 
    WHERE quest.ID = 3 AND answ.Number IN (1, 2) 

Ceci renverra une ligne par sondage (parce que vous liez seulement ID question 3 et la seule réponse à cette question), et seulement pour les enquêtes où la réponse à la question 3 est 1 ou 2.

REMARQUE: Je ne comprends pas comment vous joignez la table Questions et réponses dans votre modèle de données, donc j'ai supposé que la table Réponses a une clé étrangère à Questions appelée IDQuestion.

+0

Merci pour votre réponse. Comme je l'ai décrit, une question a beaucoup de réponses, donc je crois que votre solution peut renvoyer le même sondage plusieurs fois. S'il vous plaît noter que cela introduit le "et" problème, comment puis-je le faire avec un seul "IN"? Ne semble pas possible. –

+0

Si chaque question est jointe, via une clé étrangère, à une seule enquête et que chaque réponse est jointe, via une clé étrangère, à une seule question, le SQL devrait vous donner le bon résultat. Je ne suis pas sûr que votre modèle associe chaque réponse avec une seule _question_, c'est une condition nécessaire pour que la jointure à trois tables fonctionne. –

+0

Le problème est que beaucoup de réponses sont jointes à une seule question. Et ainsi, le même sondage et la même question sont répétés sur N lignes. Il s'agit d'une relation '1 x 0..n'. Aussi, comment faire le "1 et 2", au lieu du "1 ou 2"? (votre solution est pour "1 ou 2", l'opérateur IN) –

0
Select ... 
From Survey As 
Where Exists (
       Select 1 
       From Questions As Q1 
        Join Answers As A1 
         On A1.IdQuestion = Q1.Id 
       Where Q1.IdSurvey = S.Id 
        And Q1.Id = 3 
        And A1.Id In(1,2) 
       Having Count(*) = 2 
       ) 
+0

Que faire si je veux que les réponses soient "1 et 2" au lieu d'être "1 ou 2". Notez que votre solution est pour "1 OR 2", l'opérateur IN. –

+0

@WoF_Angel - Ok. Correctif simple. Ajoutez simplement une clause ayant. Avoir mis à jour mon message. – Thomas

+0

@WoF_Angel - Btw, ma confusion quant à ce que vous vouliez découlait de cette déclaration: «sélectionnez uniquement les enquêtes qui ont les réponses 1 et/ou 2 pour la Question3». Clairement, vous vouliez dire "réponses 1 et 2". Je l'ai pris pour signifier "1 ou 2". Sur une autre note, qu'est-ce que le '/' représente dans 'et/ou'? ;> – Thomas