Forum des développeurs  

Le forum de référence en programmation et développement. Articles, cours et tutoriels du débutant au chef de projet et DBA confirmé.
Précédent   Forum des développeurs > Bases de données > Firebird > SQL

SQL Forum d'entraide sur le SQL pour Firebird

Réponse
 
Outils de la discussion
Vieux 19/08/2008, 16h06   #1 (permalink)
Rédacteur/Modérateur
 
Avatar de giminik
 
Date d'inscription: mars 2002
Localisation: Besançon [25]
Âge: 26
Messages: 330
Envoyer un message via MSN à giminik
Par défaut Syntaxe du IN avec plusieurs colonnes

Bonjour à tous,
Je cherche à exécuter une requête de ce type : (Il s'agit juste d'un exemple pour montrer la syntaxe que je recherche)
Code :
SELECT b1.champ1
FROM base b1
WHERE (b1.champ2, b1.champ3) IN
(
SELECT DISTINCT b2.champ2, b2.champ3
FROM base b2
WHERE b2.id = 5
)
Je sais que sous Oracle on peut utiliser un IN sur plusieurs colonnes, je voudrais savoir s'il est possible avec Firebird de faire la même chose. (Cette syntaxe génère une erreur sous Firebird.)

J'ai bien effectué une recherche mais aucuns résultat...
Merci d'avance pour vos réponses.
giminik est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 19/08/2008, 16h12   #2 (permalink)
Membre Expert

 
Date d'inscription: mai 2002
Messages: 1 289
Par défaut

la réponse est non
mais si tu en disais plus on trouvera surement une solution satisfaisante
__________________
Philippe Makowski
IBPhoenix - Firebird
Membre de l'April
makowski est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 19/08/2008, 20h19   #3 (permalink)
Rédacteur/Modérateur
 
Avatar de giminik
 
Date d'inscription: mars 2002
Localisation: Besançon [25]
Âge: 26
Messages: 330
Envoyer un message via MSN à giminik
Par défaut

Bon, ça ne m'arrange pas du tout, du coup

Voici la structure simplifiée de la table sur laquelle je suis en train de travailler :
Code :
CREATE TABLE NEW_DIAGNOSTIC(
    ID INTEGER,
    CREATIONDATE DATE NOT NULL,
    CREATIONTIME TIME NOT NULL,
    PATIENT_ID INTEGER NOT NULL,
    DIAGNOSTIC_ID INTEGER NOT NULL,
    CONSTRAINT NEW_DIAGNOSTIC_PK PRIMARY KEY(ID),
    CONSTRAINT NEW_DIAGNOSTIC_PATIENT_FK FOREIGN KEY(PATIENT_ID) REFERENCES PATIENT(ID),
    CONSTRAINT NEW_DIAGNOSTIC_DIAGNOSTIC_FK FOREIGN KEY(DIAGNOSTIC_ID) REFERENCES DIAGNOSTIC(ID)
);
Et voici mes données d'entrées :

Citation:
ID CREATIONDATE CREATIONTIME DIAGNOSTIC_ID PATIENT_ID
-- ------------ ------------ ------------- ----------
1 08.08.2008 12:57:10.609 3 1
2 08.08.2008 13:09:20.843 1 2
3 08.08.2008 13:11:20.171 3 3
4 08.08.2008 13:14:01.359 5 4
5 08.08.2008 13:17:15.343 6 5
6 08.08.2008 13:22:27.234 5 6
7 08.08.2008 13:27:34.968 1 7
8 08.08.2008 16:35:02.780 1 8
9 08.08.2008 13:39:09.796 2 9
10 19.08.2008 14:12:20.000 1 8
11 19.08.2008 14:38:24.187 1 8
12 19.08.2008 14:39:35.609 3 8
Ce que je dois faire, c'est récupérer les enregistrements pour un patient (8 pour mon exemple). Ca devient donc avec un simple WHERE :
Citation:
ID CREATIONDATE CREATIONTIME DIAGNOSTIC_ID PATIENT_ID
-- ------------ ------------ ------------- ----------
8 08.08.2008 16:35:02.780 1 8
10 19.08.2008 14:12:20.000 1 8
11 19.08.2008 14:38:24.187 1 8
12 19.08.2008 14:39:35.609 3 8
À partir de là, je dois récupérer les ID des lignes contenant les couples DIAGNOSTIC_ID et PATIENT_ID qui ont la date/heure de création la plus ancienne.

Donc dans mon cas, je devrais avoir les ID 12 (puisqu'il n'y en à qu'un seul pour le couple 3/8) et 8 pour le couple 1/8 car c'est le plus ancien.

Donc, la clause IN avec plusieurs colonnes m'aurait vraiment bien aidé pour faire ça, du coup, je ne sais pas trop comment m'y prendre. J'hésite même à traiter directement les données en C++...

Si vous avez une piste ou solution je suis preneur.
giminik est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 19/08/2008, 22h58   #4 (permalink)
Membre Expert

 
Date d'inscription: mai 2002
Messages: 1 289
Par défaut

pardon ? avec le IN oracle ça s'écrirait comment ?
pour être sûr de bien comprendre
parce qu'à priori voilà :
Code :
WITH 
N2 (PATIENT_ID,DIAGNOSTIC_ID,CREATIONDATE,CREATIONTIME) 
AS 
(SELECT N1.PATIENT_ID,N1.DIAGNOSTIC_ID ,MIN(N1.CREATIONDATE),MIN(N1.CREATIONTIME) 
FROM NEW_DIAGNOSTIC N1  
WHERE N1.PATIENT_ID=8 
GROUP BY N1.PATIENT_ID ,N1.DIAGNOSTIC_ID)
 
SELECT ND.ID FROM NEW_DIAGNOSTIC ND 
JOIN N2 ON ( N2.PATIENT_ID=ND.PATIENT_ID AND N2.DIAGNOSTIC_ID=ND.DIAGNOSTIC_ID
AND N2.CREATIONDATE=ND.CREATIONDATE )
deuxième solution
Code :
SELECT ND.ID FROM NEW_DIAGNOSTIC ND 
JOIN 
(SELECT N1.PATIENT_ID,N1.DIAGNOSTIC_ID ,MIN(N1.CREATIONDATE) CREATIONDATE,MIN(N1.CREATIONTIME) CREATIONTIME
FROM NEW_DIAGNOSTIC N1  
WHERE N1.PATIENT_ID=8 
GROUP BY N1.PATIENT_ID ,N1.DIAGNOSTIC_ID) N2 
ON ( N2.PATIENT_ID=ND.PATIENT_ID AND N2.DIAGNOSTIC_ID=ND.DIAGNOSTIC_ID
AND N2.CREATIONDATE=ND.CREATIONDATE )
__________________
Philippe Makowski
IBPhoenix - Firebird
Membre de l'April

Dernière modification par makowski ; 20/08/2008 à 00h03
makowski est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 20/08/2008, 08h55   #5 (permalink)
Rédacteur/Modérateur
 
Avatar de giminik
 
Date d'inscription: mars 2002
Localisation: Besançon [25]
Âge: 26
Messages: 330
Envoyer un message via MSN à giminik
Par défaut

Bon, ça fait un moment que je n'ai pas fait de SQL, donc ce n'est certainement pas optimisé ce que j'aurais fait, mais j'aurais eu un début de piste comme ceci :
(je n'y ai pas trop réfléchi puisque j'ai eu tout de suite le problème avec le IN).
Code :
SELECT id, MIN(creationdate)
FROM new_diagnostic
WHERE patient_id = 8
AND (diagnostic_id, patient_id) IN (
SELECT DISTINCT diagnostic_id, patient_id
FROM new_diagnostic
WHERE patient_id = 8
)
GROUP BY id;
J'aurais fait ceci, je ne sais pas si c'est juste puisque je ne peux pas tester .

Merci pour ton aide, la seconde requête fonctionne super, la première, il y a une erreur de syntaxe à la première ligne. Je vais chercher pour voir comment fonctionne le WITH, cette fonction a l'air intéressante.

Petite question subsidiaire :
Avec la seconde requête :
Citation:
MIN(N1.CREATIONDATE), MIN(N1.CREATIONTIME)
Est-on certain que le champ CREATIONDATE et CREATIONTIME proviennent bien de la même ligne ?
giminik est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 20/08/2008, 10h36   #6 (permalink)
Membre Expert

 
Date d'inscription: mai 2002
Messages: 1 289
Par défaut

Le WITH a été introduit dans la version Firebird 2.1 (Common Table Expressions : http://www.firebirdsql.org/rlsnotesh...ml#rnfb210-cte)

et pardon oui, il est préférable de faire :
Code :
SELECT ND.ID FROM NEW_DIAGNOSTIC ND 
JOIN 
(SELECT N1.PATIENT_ID,N1.DIAGNOSTIC_ID ,MIN(CAST(N1.CREATIONDATE||' '||N1.CREATIONTIME AS TIMESTAMP)) CREATIONDATETIME
FROM NEW_DIAGNOSTIC N1  
WHERE N1.PATIENT_ID=8 
GROUP BY N1.PATIENT_ID ,N1.DIAGNOSTIC_ID) N2 
ON ( N2.PATIENT_ID=ND.PATIENT_ID AND N2.DIAGNOSTIC_ID=ND.DIAGNOSTIC_ID
AND N2.CREATIONDATETIME=(CAST(ND.CREATIONDATE||' '||ND.CREATIONTIME AS TIMESTAMP)) )
 
ou
Code :
WITH 
N2 (PATIENT_ID,DIAGNOSTIC_ID,CREATIONDATETIME) 
AS 
(SELECT N1.PATIENT_ID,N1.DIAGNOSTIC_ID ,MIN(CAST(N1.CREATIONDATE||' '||N1.CREATIONTIME AS TIMESTAMP)) 
FROM NEW_DIAGNOSTIC N1  
WHERE N1.PATIENT_ID=8 
GROUP BY N1.PATIENT_ID ,N1.DIAGNOSTIC_ID)
 
SELECT ND.ID FROM NEW_DIAGNOSTIC ND 
JOIN N2 ON ( N2.PATIENT_ID=ND.PATIENT_ID AND N2.DIAGNOSTIC_ID=ND.DIAGNOSTIC_ID
AND N2.CREATIONDATETIME=(CAST(ND.CREATIONDATE||' '||ND.CREATIONTIME AS TIMESTAMP)) )
__________________
Philippe Makowski
IBPhoenix - Firebird
Membre de l'April
makowski est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 20/08/2008, 10h43   #7 (permalink)
Rédacteur/Modérateur
 
Avatar de giminik
 
Date d'inscription: mars 2002
Localisation: Besançon [25]
Âge: 26
Messages: 330
Envoyer un message via MSN à giminik
Par défaut

Alors là, merci !
Si j'avais su qu'on pouvais convertir des dates + heures en timestamp, ça m'aurait bien aidé, je vais la noter quelque part cette fonction.
Merci beaucoup
giminik est déconnecté   Envoyer un message privé Réponse avec citation
Réponse

Précédent   Forum des développeurs > Bases de données > Firebird > SQL

 
Offres d' emploi informatique sur Lesjeudis.com


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are non
Pingbacks are non
Refbacks are non
Navigation rapide