UNION un peut spécial

Résolu
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 - 15 sept. 2009 à 14:10
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 - 18 sept. 2009 à 18:16
Bonjour,

Alors déjà mon objectif :
Je doit insérer dans une table les données de deux tables (de relativement grande taille, ~ 3 millions de lignes chaqu'une, jusque là facile).
Problème, des doublons (non absolus) existent. Sachant qu'une table est "prioritaire" par rapport à l'autre (je veut dire par là que si un code existe dans la table "A" la ligne du même code de la table "B" ne doit pas être insérer). Pour sa jusqu'à aujourd'hui (et encore aujourd'hui) je fessais sa en plusieurs temps :

CREATE TABLE "TMP Gère Unique"
(
   "Nbr" AS NUMERIC,
   "Code" AS TEXT, 
   CONSTRAINT "TMP Gère Unique_key" PRIMARY KEY ("Code")
);

INSERT INTO "TMP Gère Unique" ("Nbr","Code")
   SELECT Count(*) as "Nbr","Code"
   (
         SELECT "Code" FROM "A"
      UNION ALL
         SELECT "Code" FROM "B"
   ) a
   GROUP BY "Code";

INSERT INTO "Resul" (...)
      SELECT 
         ... 
      FROM 
         "A" -- J'insère tout "A"
   UNION ALL
      SELECT 
         ... 
      FROM 
         "B" a,
         "TMP Gère Unique" b 
      WHERE 
         "Nbr" = 1 
         AND 
         a."Code" =  b."Code" -- J'insère que les lignes n'existant que dans "B"
   ;

-- DROP TABLE "TMP Gère Unique";


Je sais que je peut ne pas crée de table supplémentaire (mais je vais me servir de cette table ensuite, ce qui explique aussi pk le DROP est mis en commentaire).

Problème maintenant je doit en plus intégrer les données de deux autres tables en principe (oui oui en principe ) lié à mes tables "A" et "B" (je les appellerais "1" et "2", "1" étant lié à "A" et "2" à "B")

Sauf que ces données sont mal foutue (merci à mon client ) et que certain code n'existant que dans "B" sont présent dans "1" (et vise versa). Du coup j'ajoute des colonne dans ma table temporaire puis renseigne si le "Code" existe dans "A" puis si le code existe dans "B" par requête UPDATE. Et c'est lonnnnnnnnnng...... a en mourir

Ma question maintenant (enfin ) :
Je me demandais si il ne serais pas possible de tout faire d'un seul coup. Soit un truc du genre :
CREATE TABLE "TMP Gère Unique" ("Nbr" AS NUMERIC, "Code" AS TEXT, "Existe A" BOOLEAN DEFAULT FALSE, "Existe B" BOOLEAN DEFAULT FALSE, CONSTRAINT "TMP Gère Unique_key" PRIMARY KEY ("Code"));

INSERT INTO "TMP Gère Unique" ("Nbr","Code","Existe A","Existe B")
SELECT Count(*) as "Nbr","Code","Existe A","Existe B"
(
   SELECT "Code",TRUE AS "Existe A",NULL AS "Existe B" FROM "A"
   UNION ALL
   SELECT "Code",NULL AS "Existe A",TRUE AS "Existe B" FROM "B"
)
GROUP BY "Code" -- <- ICI IL EN MANQUE UN BOUT;


Soit je voudrais que si un 'TRUE' est présent pour un code ce même 'TRUE' soit insérer dans ma table (heeeeee je ne sait pas si je suis bien claire en faite ). Autrement dit je voudrais que le TRUE soit 'prioritaire' par rapport à NULL dans mon UNION (je ne me sent toujours pas claire mais je ne voie pas comment le dire autrement ).

Help me... Les temps de traitement vos avoir raison de ma santé mental (déjà que je ne suis pas très équilibré )

Amicalement

PS :
(je travail pour le moment dans PostreSQL mais mes requêtes doivent être compatibles à d'autre SGBD ce qui explique pk mon poste est dans "SQL/Autre/Requêtes" et non dans PostgreSQL)

1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo

3 réponses

Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
15 sept. 2009 à 15:18
Sa y est, et tout seul comme un grand
Ma solution :
SELECT 
   CASE 
      WHEN a."Code" IS NULL THEN b."Code" 
      ELSE a."Code" END as "Code",
      "Présent A",
      "Présent B" 
   FROM
         (SELECT "Code",true as "Présent A" FROM "A") a
      FULL OUTER JOIN 
         (SELECT "Code", true as "Présent B" FROM "B") b 
      ON (a."Code" = b."Code") 

Bon bà peut être que sa servira à quelqu'un un jours.

Si quelqu'un à mieux qu'il n'hésite surtout pas

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
3
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
18 sept. 2009 à 18:16
J'ai encore mieux
SELECT 
   CASE 
      "Code",
      Max("Présent A"),
      Max("Présent B") 
   FROM
     (
         SELECT "Code",1 as "Présent A",0 as "Présent B" FROM "A"
      UNION ALL
         SELECT "Code",0 as "Présent A",1 as "Présent B" FROM "B"
     )
   GROUP BY "Code"

Et poupouf plus de CASE WHEN ... (je pense que sa sera plus rapide même si je n'est pas encore testé à vrais dire )

Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
3
Polack77 Messages postés 1098 Date d'inscription mercredi 22 mars 2006 Statut Membre Dernière intervention 22 octobre 2019 1
15 sept. 2009 à 14:59
Je pense que je ne suis pas très loin de la solution mais sa ne veut toujours pas faire ce que veut veut
Au faite les requête de création/alimentation de mes table de testes :
CREATE TABLE "A" ("Code" text NOT NULL,CONSTRAINT "A_pkey" PRIMARY KEY ("Code"));
INSERT INTO "A"("Code") VALUES ('a'),('b'),('c'),('d'),('e');
CREATE TABLE "B" ("Code" text NOT NULL,CONSTRAINT "B_pkey" PRIMARY KEY ("Code"));
INSERT INTO "B"("Code") VALUES ('c'),('d'),('e'),('f'),('g');

J'obtiens soit les clefs de A avec :
SELECT a."Code","Présent A","Présent B" FROM
(SELECT "Code",true as "Présent A" FROM "A") a
LEFT OUTER JOIN 
(SELECT "Code", true as "Présent B" FROM "B") b 
ON (a."Code" = b."Code")

Soit les clefs de B mais jamais les deux
SELECT b."Code","Présent A","Présent B" FROM
(SELECT "Code",true as "Présent A" FROM "A") a
RIGHT OUTER JOIN 
(SELECT "Code", true as "Présent B" FROM "B") b 
ON (a."Code" = b."Code")


Amicalement
1000 recherches sur Google = 1Km de voiture en CO² (réfuté par Google )
1000 recherches sur Forestle = 100 m² de forêt tropicale sauvé .
Surfez écolo
0
Rejoignez-nous