Requête SQL (Access) : données sans liens entre elles

Requête SQL (Access) : données sans liens entre elles - SQL/NoSQL - Programmation

Marsh Posté le 19-11-2007 à 22:07:09    

Bonjour, je cherche à faire une requête permettant d'afficher 2 types de données sans lien entre elles, et sans doublons. Ma BDD est celle d'une bibliothèque, et la requête doit afficher d'une part tous les auteurs du 19eme siecle, et d'autre part tous les éditeurs du 20eme siecle. Je sais qu'il faut passer par un UNION ; voici les 2 tables sur lesquelles on travaille pour cette requete :
http://pix.nofrag.com/b/4/f/d9f9cf7c5cea8c4589efffa6bff2e.jpg
la date d'edition est un numérique correspondant à l'année, et la date de naissance de l'auteur en format date (les conditions de sélection ne sont pas un problème, le seul problème est l'affichage des 2 résultats en 2 colonnes, et sans doublons).
D'avance merci.


Message édité par hervai le 22-11-2007 à 17:52:23
Reply

Marsh Posté le 19-11-2007 à 22:07:09   

Reply

Marsh Posté le 20-11-2007 à 07:41:10    

Pour ne pas avoir de doublon, on utilise habituellement le mot clef "distinct".
 
Requête pour avoir la liste des éditeurs du 20e siècle

select distinct Nom_editeur
  from Editeur
 where Date_edition >= '19000101' and Date_edition < '20000101'

(A adpater en fonction de la base de données pour le formatage de la date, là j'ai pris le formatage Sybase)
 
Requête pour avoir la liste des auteurs du 19e siècle

select distinct Nom_auteur
  from Auteur
 where (Date_naissance_auteur >= "18000101" and Date_naissance_auteur < "1900101" )
    or (Date_deces_auteur >= "18000101" and Date_deces_auteur < "1900101" )

(A adpater en fonction de la base de données pour le formatage de la date, là j'ai pris le formatage Sybase)
 
Si l'on veut mettre bout à bout ces deux listes, on mettra le mot clef "union" entre les deux requêtes. il faudra aussi que les noms des colonnes soient les mêmes pour les deux requêtes. Pour cela, on utilisera des alias.
 
Mais le problème est différent. Il semble qu'il ne s'agisse pas de mettre les résultats bout à bout, mais côte à côte. Dans ce cas, il ne faut pas utiliser "union". On mettra nos deux requêtes en sous-requête d'une requête principale :

select
 (select distinct Nom_editeur
  from Editeur
 where Date_edition >= '19000101' and Date_edition < '20000101'),
(select distinct Nom_auteur
  from Auteur
 where (Date_naissance_auteur >= "18000101" and Date_naissance_auteur < "1900101" )
    or (Date_deces_auteur >= "18000101" and Date_deces_auteur < "1900101" )

Sous Oracle, il faudra peut-être ajouter "from dual" parce qu'Oracle aime bien qu'un nom de table soit spécifié.

Reply

Marsh Posté le 20-11-2007 à 10:06:21    

non la ca ne va pas marcher, pour mettre un sous-select a cet endroit il faut qu'il ne retourne qu'une seule valeur.
 
je suis pas vraiment sur de saisir ce que tu veux, tu pourrais faire donner un exemple concret avec des données?

Reply

Marsh Posté le 20-11-2007 à 12:19:16    

Bonne remarque, mais, justement, ici, chaque sous-select ne retourne qu'une seule colonne, donc cela devrait marcher (en tous cas sous Oracle (mais je ne peux pas tester, je suis bloqué chez moi à cause des grrrr...)).

Reply

Marsh Posté le 20-11-2007 à 14:05:12    

il ne faut jamais penser en terme de colonne mais en terme de ligne en sgbd :)

Reply

Marsh Posté le 20-11-2007 à 17:23:51    

Voilà ce que ca m'affiche en faisant la requete d'olivthill :  
http://pix.nofrag.com/5/0/1/6232a151ed8093b607843791d9877.jpg

Reply

Marsh Posté le 20-11-2007 à 17:33:30    

Code :
  1. SELECT 'Auteur' type, nom_auteur nom
  2. FROM auteur
  3. WHERE date_naissance_auteur BETWEEN '01/01/1800' AND '31/12/1899'
  4. OR date_deces_auteur BETWEEN '01/01/1900' AND '31/12/1999'
  5. union
  6. SELECT 'Editeur' type, nom_editeur nom
  7. FROM edite
  8. WHERE date_edition BETWEEN '01/01/1900' AND '31/12/1999'


 
PS : Pas besoin de DISTINCT étant donné que le UNION fait déjà un DISCTINCT (pour ne pas faire le distinct automatique, utiliser UNION ALL)


Message édité par MagicBuzz le 20-11-2007 à 17:34:17
Reply

Marsh Posté le 20-11-2007 à 17:35:18    

PS : Pour les auteurs, si un auteur est né à la fin du 18° et mort au début du 20°, la requête ne marche pas. Mais bon ça doit pas courir les rues... C'est à toi de voir si tu prends ou non en compte ce cas.
 
Ensuite, pour décider si un auteur est contemporain d'une époque, je ne sais pas si des critères sur sa date de naissance et de décès sont suffisants... Généralement on prendra plutôt les dates de parutions de ses bouquins non ?

Message cité 1 fois
Message édité par MagicBuzz le 20-11-2007 à 17:36:03
Reply

Marsh Posté le 20-11-2007 à 17:59:57    

SELECT 'Auteur' type
 
Je ne comprend pas bien les ' ' et le "type" , en tout cas écrit tel quel ca ne marche pas.

Reply

Marsh Posté le 20-11-2007 à 18:26:58    

MagicBuzz a écrit :

Ensuite, pour décider si un auteur est contemporain d'une époque, je ne sais pas si des critères sur sa date de naissance et de décès sont suffisants... Généralement on prendra plutôt les dates de parutions de ses bouquins non ?

Personellement, je considère qu'un auteur est contemporain à l'époque où il a vécu et non pas aux périodes correspondants aux dates de première parution de ses écrits. Il existe trop de cas où des textes n'ont été publié que plusieurs années après la mort d'un auteur pour pouvoir se baser là dessus.
 
Pour prendre un auteur très célèbre : Victor Hugo. Certains de ses écrits n'ont été retrouvé que plusieurs décennies après sa mort. La seule publication qui est considéré comme comprenant l'intégralité de ses écrits date d'ailleurs de 2001 et elle contenait quelques inédits (certes pas dans la catégorie "romans" ) . Ca n'en fait pas pour autant un contemporain de Bernard Werber.
 

hervai a écrit :

SELECT 'Auteur' type
 
Je ne comprend pas bien les ' ' et le "type" , en tout cas écrit tel quel ca ne marche pas.


Ca, ça veut dire : retourne moi la valeur 'Auteur' dans la colonne de nom 'type' pour chaque ligne du résultat. C'est un raccourcis qui permet d'avoir une colonne dont la valeur est fixe.

Message cité 1 fois
Message édité par omega2 le 20-11-2007 à 18:28:38
Reply

Marsh Posté le 20-11-2007 à 18:26:58   

Reply

Marsh Posté le 20-11-2007 à 19:30:25    

omega2 a écrit :

Personellement, je considère qu'un auteur est contemporain à l'époque où il a vécu et non pas aux périodes correspondants aux dates de première parution de ses écrits. Il existe trop de cas où des textes n'ont été publié que plusieurs années après la mort d'un auteur pour pouvoir se baser là dessus.


Ouais, enfin... Je voulais dire "date à laquel il a écrit". Le mot "publié" effectivement n'était pas approprié ;)
D'un autre côté, prendre en compte un auteur né en 1898 dans les auteurs du 19° je sais pas si c'est très malin non plus ;) M'enfin j'imagine qu'il y a une règle établie qui permet de décider ou non si une personne est contemporaine d'une époque ou non, et ce, que ce soit en rapport ou non avec son activité :)
 

omega2 a écrit :


Ca, ça veut dire : retourne moi la valeur 'Auteur' dans la colonne de nom 'type' pour chaque ligne du résultat. C'est un raccourcis qui permet d'avoir une colonne dont la valeur est fixe.


Effectivement. Ici, ça te permet de différencier les noms qui correspondent à un auteur et les lignes qui correspondent à un éditeur, parceque je trouve ça un peu étrange de vouloir les mélanger.
Si t'as besoin de retrouver qu'une liste de noms, tous "type" confondu, et sans doublons, alors vire simplement cette clause.


Message édité par MagicBuzz le 20-11-2007 à 19:32:24
Reply

Marsh Posté le 20-11-2007 à 20:40:29    

Dans tous les cas ça ne compile pas sous access :(

Reply

Marsh Posté le 20-11-2007 à 22:46:13    

et ça dit quoi comme erreur ? comment ça ça compile pas ? essaie de faire :
 

Code :
  1. SELECT 'Auteur' AS [type], nom_auteur AS nom
  2. FROM auteur
  3. WHERE date_naissance_auteur BETWEEN '01/01/1800' AND '31/12/1899'OR date_deces_auteur BETWEEN '01/01/1900' AND '31/12/1999'
  4. union
  5. SELECT 'Editeur' AS [type], nom_editeur AS nom
  6. FROM edite
  7. WHERE date_edition BETWEEN '01/01/1900' AND '31/12/1999'

Reply

Marsh Posté le 21-11-2007 à 09:55:53    

hervai > Note pour plus tard : Toujours préciser quand on bosse avec access comme base de donnée, il a des règles d'écriture des requêtes qui différent des autres. ;)

Reply

Marsh Posté le 22-11-2007 à 16:35:12    

MagicBuzz a écrit :

et ça dit quoi comme erreur ? comment ça ça compile pas ? essaie de faire :
 

Code :
  1. SELECT 'Auteur' AS [type], nom_auteur AS nom
  2. FROM auteur
  3. WHERE date_naissance_auteur BETWEEN '01/01/1800' AND '31/12/1899'OR date_deces_auteur BETWEEN '01/01/1900' AND '31/12/1999'
  4. union
  5. SELECT 'Editeur' AS [type], nom_editeur AS nom
  6. FROM edite
  7. WHERE date_edition BETWEEN '01/01/1900' AND '31/12/1999'



 
Lorsque je compile j'ai cette erreur :
Type de données incompatibles dans l'expression du critère.
 
Sinon, quelqu'un saurait me dire comment faire la somme de SUM(x) et SUM(y) (donc la somme de 2 sommes)?
Aussi, je dois faire une requête qui m'affiche tous les livres appartenant à la fois à la catégorie SF et Aventure, et qui sont loués. Voici mon diagramme de relations et mes données :
http://pix.nofrag.com/3/c/e/1134cc926f9e5e7031ec271ffef20.jpg
http://pix.nofrag.com/4/2/5/9677837f454e6e8ab374f6e996055.jpg


Message édité par hervai le 22-11-2007 à 16:40:25
Reply

Marsh Posté le 22-11-2007 à 16:55:57    

date est de quel type ?
 
je vois dans ta table "livre" que c'est l'année uniquement, sous forme numérique, et non pas une date. c'est pareil pour tout le reste ?
 
si oui ben... corrige de toi-même... moi je suis parti du principe qu'un champ nommé date était de type date et contenait une date, mais visiblement c'était un peu trop logique comme raisonnement :o

Reply

Marsh Posté le 22-11-2007 à 16:59:38    

Non en fait quasiment toutes les dates sont de type date, exceptés la date d'édition et la date de redaction.

Reply

Marsh Posté le 22-11-2007 à 17:03:48    

bah je vois pas pkoi la requête que j'ai écrit marche pas.

Reply

Marsh Posté le 22-11-2007 à 17:12:20    

Ta requête marche, elle renvoie ca :  
http://pix.nofrag.com/0/8/7/8dc88d768556b50a802613067eaa9.jpg
 
Moi je voudrais qu'elle renvoie un truc comme ça sans les doublons :
http://pix.nofrag.com/d/e/2/254268aea57dd40e42c067f712174.jpg
donc dans la colonne de gauche les 6 auteurs en 6 lignes, et dans la colonne de droite les 8 editeurs en 8 lignes (c'est possible au moins ce que je demande ?)

Reply

Marsh Posté le 22-11-2007 à 17:52:32    

impossible, point à la ligne.
 
et je t'invite à regarder ma signature, histoire de comprendre pourquoi c'est impossible, et pourquoi c'est pas dérangeant.


Message édité par MagicBuzz le 22-11-2007 à 17:53:13
Reply

Marsh Posté le 22-11-2007 à 17:56:02    

Ok, je vais utiliser ta requête. Sinon, tu saurais répondre à mes 2 autres questions (somme de 2 sommes, et afficher les livres qui sont à la fois en SF et en Aventure) ?

Reply

Marsh Posté le 22-11-2007 à 19:22:51    

somme de deux sommes ? qu'entends-tu par là ? c'est pas plutôt l'adition de deux sommes plutôt ?
 

Code :
  1. SELECT champ1, sum(champ2) + sum(champ3) AS total
  2. FROM latable
  3. GROUP BY champ1


 
Sinon, détail ta demande.
 
Pour la seconde question, c'est plus chaud.
 
Le plus simple :
 
Sélectionne les livres en faisant une jointure sur les propriétés (table "possede" si je ne m'abuse)
 
Dans ton where, filtre les lignes de possède où nom_categorie = 'Aventure' or nom_categorie = 'SF'
 
Dans la clause de ton select, ajoute un count(*)
Fait un group by par le nom du livre
 
Et rajoute une clause having count(*) = 2
 
En fait, tu récupères toutes les propriétés des lignes qui sont soit aventure soit sf.
Puis tu comptes ces catégories trouvés (donc par livre, 1 ou 2).
Et tu ne gardes que les lignes où ce compte est égale à 2, c'est à dire que le bouquin a bien les deux catégories (en partant du principe que tu n'as pas de doublons dans la table "possede" )

Reply

Marsh Posté le 22-11-2007 à 19:24:47    

ceci dit c'est pas completement impossible, il me semblait bien qu'il voulait faire ca depuis le début, en access je sais pas, mais en oracle si je devais absolument le faire (jvois pas trop pourquoi mais bon),  
 
je m'arrangerai pour avoir les valeurs distinctes associées a un numero incrementé (un rank) et je les croiserai en full outer join
 
mais globalement y a pas de sens a la ligne ca je trouve plus emmerdant

Message cité 1 fois
Message édité par casimimir le 22-11-2007 à 19:27:02
Reply

Marsh Posté le 22-11-2007 à 19:36:28    

casimimir a écrit :

ceci dit c'est pas completement impossible, il me semblait bien qu'il voulait faire ca depuis le début, en access je sais pas, mais en oracle si je devais absolument le faire (jvois pas trop pourquoi mais bon),  
 
je m'arrangerai pour avoir les valeurs distinctes associées a un numero incrementé (un rank) et je les croiserai en full outer join
 
mais globalement y a pas de sens a la ligne ca je trouve plus emmerdant


quand j'ai dit "impossible" effectivement, c'est juste pour signifier que de base, c'est pas jouable sans partir dans un mic mac aussi bancal que possible.
 
mais surtout (mon renvoi vers ma signature va dans ce sens) un SGBD n'a pas pour vocation de mettre en forme les informations, mais de les gérer et savoir les retrouver.
la requête que j'ai proposé est donc amplement suffisante dans la mesure où elle retrouve bien les données, et on sait distinquer les éditeurs des auteurs. ensuite, si on veut les afficher d'une certaine manière, c'est au programme consommateur de la requête de faire les traîtements nécessaires sur le résultat.


Message édité par MagicBuzz le 22-11-2007 à 19:36:50
Reply

Marsh Posté le 22-11-2007 à 19:43:31    

MagicBuzz a écrit :

somme de deux sommes ? qu'entends-tu par là ? c'est pas plutôt l'adition de deux sommes plutôt ?
 

Code :
  1. SELECT champ1, sum(champ2) + sum(champ3) AS total
  2. FROM latable
  3. GROUP BY champ1


 
Sinon, détail ta demande.
 
Pour la seconde question, c'est plus chaud.
 
Le plus simple :
 
Sélectionne les livres en faisant une jointure sur les propriétés (table "possede" si je ne m'abuse)
 
Dans ton where, filtre les lignes de possède où nom_categorie = 'Aventure' or nom_categorie = 'SF'
 
Dans la clause de ton select, ajoute un count(*)
Fait un group by par le nom du livre
 
Et rajoute une clause having count(*) = 2
 
En fait, tu récupères toutes les propriétés des lignes qui sont soit aventure soit sf.
Puis tu comptes ces catégories trouvés (donc par livre, 1 ou 2).
Et tu ne gardes que les lignes où ce compte est égale à 2, c'est à dire que le bouquin a bien les deux catégories (en partant du principe que tu n'as pas de doublons dans la table "possede" )


 
A vrai dire je comprend pas très bien comment faire ce que tu décris, je suis vraiment novice en SQL, je connais le SELECT, COUNT, SUM ..., ça va pas beaucoup plus loin :s

Reply

Marsh Posté le 22-11-2007 à 20:01:48    

Bah lis doucement, c'est pourtant tout détaillé dans mon post ;)
 
Vu qu'on ne résoud pas les éxercices, et que ta demande me fait de plus en plus penser à un exercice, désolé, mais je ne détaillerai pas plus :p

Reply

Marsh Posté le 22-11-2007 à 20:48:46    

A vrai dire c'est le "having count(*) = 2" avec lequel j'ai du mal : je ne vois pas trop comment tu l'utilises ; pour le reste je pense pouvoir me débrouiller, même si à mon avis il y a une méthode plus facile (je ne vois pas laquelle mais j'en suis sûr).

Reply

Marsh Posté le 22-11-2007 à 22:36:16    

je doute que tu trouves plus simple. tu peux jouer à coup de sous-requêtes, mais niveau algo, c'est plus complexe, niveau syntaxe aussi, niveau performances, c'est loin derrière, et niveau support par les différents sgbd c'est ças génial. donc non. c'est la solution la plus simple.
 
pour le having, fait une recherche sur le net. le moindre exemple sera extrêment proche de ton exercice, tu peux en etre sur.

Reply

Marsh Posté le 22-11-2007 à 22:52:25    

Dès que je met le count(*), ca me met un msg d'erreur :  
Vous avez essayé d'exécuter une requête ne comprenant pas l'expression spécifiée 'Ref_livre' comme une partie de la fonction d'agrégat.
 
 
Voici comment j'ai écrit la requête :

Code :
  1. SELECT Livre.Ref_livre,Livre.Titre_livre,count(*)
  2. FROM Livre, Categorie, Location, Possede
  3. WHERE Livre.Ref_livre=Possede.Ref_livre AND Possede.Nom_categorie=Categorie.Nom_categorie AND Livre.Ref_livre=Location.Ref_livre AND (Possede.Nom_categorie='Science-fiction' or Possede.Nom_categorie='Aventure') AND Location.Date_retour IS NULL
  4. GROUP BY Livre.Titre_livre
  5. HAVING count(*)=2;

Reply

Marsh Posté le 23-11-2007 à 08:12:51    

normal, tu ne respectes pas la syntaxe du group by.
il doit avoir l'ensemble des champs que tu sélectionnes mais qui ne font pas parti d'une fonction d'agrégation. là t'as mis le titre du livre, mais pas sa référence.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed