probleme requete jointure et distinct

probleme requete jointure et distinct - SQL/NoSQL - Programmation

Marsh Posté le 15-07-2008 à 16:56:45    

Bonjour,
 
Je suis sous oracle et j'ai une requête toute bête avec 3 jointures entre 4 tables mais j'ai un problème lorsque je mets le distinct :
 

Code :
  1. select
  2. distinct tmp1.pin_number,
  3. tmp1.cfa,
  4. tmp1.name_prefix,
  5. tmp1.name_suffix,
  6. tmp1.dob,
  7. tmp1.verified_flag,
  8. tmp1.work_phone,
  9. tmp1.start_travel_date,
  10. tmp1.end_travel_date,
  11. tmp1.home_appart_code,
  12. tmp1.home_city_code,
  13. tmp1.pin_mailer_sent,
  14. tmp1.is_arranger_flag,
  15. tmp1.bus_traveler_rollup_type_desc,
  16. tmp1.arranger_first_name,
  17. tmp1.arranger_last_name,
  18. tmp1.arranger_phone,
  19. tmp1.email_type,
  20. tmp1.arranger_email,
  21. tmp1.receive_e_invoice_flag,
  22. tmp1.traveler_type_name,
  23. tmp1.privacy_option_acceptance_flag,
  24. tmp1.client_org_unit_id,
  25. tmp2.credit_card_vendor_code,
  26. tmp2.credit_card_description,
  27. tmp2.credit_card_number,
  28. tmp2.expiration_date,
  29. tmp2.preferred_hotel_guarantee_flag,
  30. tmp2.preferred_for_air_flag,
  31. tmp2.preferred_car_guarantee_flag,
  32. tmp3.personal_email,
  33. tmp3.alternate_email,
  34. tmp3.state_province_code,
  35. tmp3.state,
  36. tmp3.country,
  37. tmp3.code_entite,
  38. tmp3.matricule,
  39. tmp3.matricule1,
  40. tmp3.secretaire,
  41. tmp4.vendor_group,
  42. tmp4.vendor_code,
  43. tmp4.membership_number,
  44. tmp4.govt_issued_document,
  45. tmp4.visa_exp_date,
  46. tmp4.issuance_country_code,
  47. tmp4.traveler_corp_discount_number,
  48. tmp4.vendor_discount_discgroup,
  49. tmp4.vendor_code1,
  50. tmp4.expiration_date1
  51. FROM tmp_export_profils_portrait tmp1, tmp_export_profils_portrait2 tmp2,
  52. tmp_export_profils_portrait3 tmp3, tmp_export_profils_portrait4 tmp4
  53. WHERE tmp1.pin_number = tmp2.pin_number
  54. AND tmp2.pin_number = tmp3.pin_number
  55. AND tmp3.pin_number = tmp4.pin_number;


 
Si j'enlève le distinct ça marche mais les doublons sont toujours présents.
 
Comment faire ?
 
Merci

Reply

Marsh Posté le 15-07-2008 à 16:56:45   

Reply

Marsh Posté le 15-07-2008 à 17:13:28    

1/ apprends à écrire une jointure
2/ peux-tu "réduire" ton problème: essayer sans certains champs et trouver la requête "minimum" qui présente le problème
3/ QUEL EST LE PROBL7ME PRODUIT PAR LE REQUETE AVEC LE DISTINCT??? /FOU /FOU


---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 15-07-2008 à 17:23:41    

Les jointures sont bonnes, hormis le fait que je n'utilise pas des mots clés comme JOIN ou INNER JOIN, etc...
Le problème est que si j'ai un nombre de champs trop important dans le select il me met l'erreur :
 
ORA-01114 : IO error writing block to file 201 (block # 17447)
ORA-27072 : File I/O error
...
 
d'où ma question :
 
Est-ce qu'il y a un nombre maximum de champs à spécifier sous dans le select où il y a un distinct ?
 
Le plus fou c'est que si j'enlève les derniers champs à partir de tmp3.country ça marche.Ca marche de même si j'enlève le distinct et que je mets tous les champs.Mais quand je mets les deux ça ne marche pas.
 
Merci.
Je précise que j'éxecute cette requête sous PL/SQL developer.

Reply

Marsh Posté le 16-07-2008 à 09:54:16    

Tes jointures sont certes bonnes mais cela doit faire environ 10 ans qu'on a arreté de les écrires comme ça. Quand tu postes sur un forum, si tu veux que ta question "touche" le plus grand nombre de personne, il est préférable d'utiliser l'écriture "standard d'aujourd'hui"

 

Quand à l'erreur ( c'est plus facile avec le code), je suis vraiment pas expert oracle mais un petit coup d'oeil sur la doc nous donne:

Citation :

ORA-01114: IO error writing block to file
Cause: The device on which the file reside is probably offline. If the file is a temp file, then it is also possibale that the device has run out of space.This could happen because disk space of temporary file is not necessarily allocated at file creation time.
Action: Restore access to the device OR remove unnecessary files to free up space.


Donc je dirais que ta requête de la mort bourrine tellement le fichier temp que celui-ci dépasse sa taille max.
Je vérifierais donc la taille du-dit fichier sur le tablespace associé, voir la taille dispo sur le disque tout court.


Message édité par anapajari le 16-07-2008 à 09:55:06

---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 16-07-2008 à 10:18:19    

ok j'ai fait des left join à la place. Mais cela me parait bizarre quand même qu'en rajoutant un distinct sur un champ il bourrine le fichier temp alors qu'en principe le distinct devrait ressortir moins de résultats et par conséquent bourriner plus le fichier temp. Or ça marche bien...
 
Je capte pas trop !

Reply

Marsh Posté le 16-07-2008 à 10:56:48    

inner join, pas left bourdel !
 
t'as des (+) dans ta requête ? non. donc INNER :o
 
t'as vraiment envie de foutre Oracle par terre toi...
 
ensuite, c'est quoi la taille de tes champs ? genre des varchar2(4000) chacuns non ? c'est pas le nombre de champs qui est limité (enfin, si, il est limité aussi, mais pour ainsi dire impossible à atteindre), mais la taille des lignes. un distinct augmente vraissemblamement la taille des lignes lors du traîtement

Reply

Marsh Posté le 16-07-2008 à 11:12:46    

Ok, merci magicBuzz je vais voir de ce côté là

Reply

Marsh Posté le 16-07-2008 à 12:16:30    

En fait j'ai beau mettre les champs aussi petit qu'il se peut (à savoir que max j'ai des champs qui font varchar2(55), et ça ne change rien, j'ai toujours ce problème de File I/O.
 
Ma requête est-elle mauvaise ou alors y a t'il un moyen autre pour que je n'ai pas ce problème ?
 
En fait mon probleme est le suivant : j'ai 4 tables tmp_export_profils_portrait[1-2-3-4] et dans celles-ci je dois retirer pour une personne plusieurs informations dans 4 tables.
 
Pour moi la seule chose qui les rattache est pin_number (qui est l'id de la personne en question) et qu'on retrouve dans les 4 tables, donc ma question est la suivante :
 
Est-ce que les jointures de ma requete SQL est bonne ?
 

Code :
  1. SELECT
  2. tmp1.pin_number,
  3. ...(champs cités plus haut dans le premier post)
  4.             FROM tmp_export_profils_portrait tmp1
  5.             INNER JOIN tmp_export_profils_portrait2 tmp2 ON tmp1.pin_number = tmp2.pin_number
  6.             INNER JOIN tmp_export_profils_portrait3 tmp3 ON tmp2.pin_number = tmp3.pin_number
  7.             INNER JOIN tmp_export_profils_portrait4 tmp4 ON tmp3.pin_number = tmp4.pin_number;


 
Par ce qu'au final j'ai des doublons qui ressortent
 
Merci


Message édité par krovomi le 16-07-2008 à 12:34:50
Reply

Marsh Posté le 16-07-2008 à 14:36:25    

je dirais que t'es tombé sur un bug d'oracle.
 
vire un maximum de champs, puis rajoute-les un à un, jusqu'à ce que l'erreur se produise
 
dès qu'elle se produit, vire le champ qui pose problème, et tente un autre.
 
si ça continue de planter, bravo t'as gagné : un joli bug oracle.
 
à mon avis le distinct est limité à un nombre de champs bien définis, ou une connerie du genre.
 
 
ah... au fait. tu peux faire un select (sans le distinct) et lire toutes les lignes (genre tu lances la requête dans SQL+)
 
parceque ton truc ça me rappelle aussi ce qui se passe quand t'as un fichier de base corrompu : le distinct nécessite une lecture réelle de chaque valeur de chaque champs, alors que le select normal ne nécessite que la lecture des indexs et champs utilisés pour les filtres, donc si t'as des données corrompues à un endroit, il ne s'en rendra pas compte

Reply

Marsh Posté le 16-07-2008 à 14:45:43    

tes jointures sont bonnes mais si tu ne mets pas de distinct tu te retrouves evidemment avec des doublons.
 
D'ailleurs ils proviennent de quelle table? Une table en particulieur ou tu as des données doublonnées dans les 4?


---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 16-07-2008 à 14:45:43   

Reply

Marsh Posté le 16-07-2008 à 15:12:49    

@MagicBuzz : Je fais tous mes tests sous PL/SQL developer, et oui je peux faire un select sans le distinct, ça ne pose pas de problème particulier.
 
@anapajari : j'ai des doublons dans les tables. je m'explique : En fait ces 4 tables ont plus ou moins la même architecture au niveau des champs, sauf que dans certaines il y a des champs en plus ou en moins, mais par exemple on aura toujours l'id, le nom et prenom d'une personne.  
 
Le but de ma requête est : pour une personne donnée, récupérer tout ce qui le concerne sur les 4 tables (en virant les champs qui se répètent).
 
Mais là je sèche avec cette histoire de distinct.
 
j'ai essayé une autre manière mais je crois qu'il va également me rajouter des doublons, je me trompe ?

Code :
  1. SELECT 
  2.             tmp1.pin_number,
  3.             ...
  4.             tmp4.expiration_date1
  5.             FROM tmp_export_profils_portrait tmp1
  6.             FULL OUTER JOIN tmp_export_profils_portrait2 tmp2 ON tmp1.pin_number = tmp2.pin_number
  7.             FULL OUTER JOIN tmp_export_profils_portrait3 tmp3 ON tmp2.pin_number = tmp3.pin_number
  8.             FULL OUTER JOIN tmp_export_profils_portrait4 tmp4 ON tmp3.pin_number = tmp4.pin_number;


Message édité par krovomi le 16-07-2008 à 15:13:05
Reply

Marsh Posté le 16-07-2008 à 15:47:59    

essaye en faisant des sous-select qui contiennent le distinct de chaque table


---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 16-07-2008 à 15:53:57    

Une autre question :
 
Sur les 4 tables, il y en a qui ont plus d'enregistrement que d'autres, si je veux récupérer toutes les données sur les 4 tables pour une personne et que pour les champs non renseignés (NULL), il ne me mette rien, il vaut mieux que je fasse un  
 

Code :
  1. SELECT ...
  2. FROM table_contenant_le_plus_denregistrements
  3. RIGHT OUTER JOIN deuxieme_table_contenant_le_plus_denregistrements
  4. ...


 
afin qu'il ne me mette pas des données comme cela (sorti fichier plat, champs séparés par un pipe :
 
||||||||||||||||Carte de Fidelite||DER|||||||||||||||||||
 
exemple de bon format :
 
1547697|13017|Mme|Fran|NEGRESSSSSSSS|fra.negre@toto.com|23, rue du BOURG|CHAMPIGNY|Carte de Fidelite||DER|
 
Je ne sais pas si vous voyez ce que je veux dire...

Reply

Marsh Posté le 16-07-2008 à 15:56:21    

nan mais left outer c'est plus lisible que right :o
Et tu noteras que c'est pas ce que faisait ta requete initialle.


---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 16-07-2008 à 16:00:08    

Bien sur, mais je n'y connais absolument rien en requete ca n'est pas mon domaine, c'est juste pour dépanner que je suis dessus, donc je test un peu

Reply

Marsh Posté le 16-07-2008 à 18:05:27    

bon, et ce test dans SQL+ ?
 
SQL Developper, comme TOAD, ne fetch pas toutes les lignes, dont si des données sont corrompues, ça ne fera pas d'erreur.
 
moi je veux que tu fasse un SQL+ pour voir si tu te paies un message d'erreur au milieu.
 
 
 
si tu me crois pas, rempli une table avec des nombres de 0 à 1000
 
fait un "select 1/nombre from matable order by nombre desc"
 
et tu verras que sql developper ne fera pas d'erreur, alors que sql+ va te sortir un bon gros division par zero blue screen of death qui tue (bon, sans blue screen quand même, mais un joli message d'erreur ;))


Message édité par MagicBuzz le 16-07-2008 à 18:06:58
Reply

Sujets relatifs:

Leave a Replay

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