1
votes

Pouvez-vous avoir plusieurs instructions de sélection sur une seule table, puis les joindre?

Veuillez noter que je ne suis pas un développeur, donc toute aide ici serait grandement appréciée.

Mon problème: J'ai une liste dans Oracle Responsys qui contient tous les clients réservés pour une tournée. Je veux trouver tous les enregistrements qui ont des valeurs manquantes pour FIRST_NAME (qui peut être Tba / Tbc / Null), afin que je puisse envoyer au booker principal un e-mail lui demandant de mettre à jour les détails du nom de ses invités supplémentaires.

Le booker principal aura toujours une valeur CUSTOMER_ID_ se terminant par «-1». Les enregistrements avec des valeurs de prénom manquantes ne le seront pas.

Ce que je veux faire, c'est sélectionner tous les enregistrements de la liste qui ont des valeurs de prénom manquantes, les grouper par BOOKING_LOCATOR (une valeur partagée par le principal booker et leurs invités supplémentaires) - ALORS ne renvoient que les principaux bookers (enregistrements avec CUSTOMER_ID_ se terminant par '-1'.

Jusqu'à présent, j'ai reconstitué cette idée approximative de ce que je veux en regardant d'autres messages, mais il ne renvoie rien comme ce que je cherche:

SELECT $A$.BOOKING_LOCATOR, $A$.CUSTOMER_ID_, $A$.EMAIL_ADDRESS_
FROM
(
  SELECT $A$.BOOKING_LOCATOR FROM $A$ WHERE ($A$.FIRST_NAME IN ('TBA', 'TBC', 'Tba', 'Tbc') OR $A$.FIRST_NAME IS NULL) AND $A$.POLAR_BOOKING_STATUS != 'C' AND $A$.BOOKING_STATUS != 'Waitlist' AND $A$.EMBARK_DATE >= SYSDATE+1
  GROUP BY $A$.BOOKING_LOCATOR
) $A$
INNER JOIN (
  SELECT $A$.BOOKING_LOCATOR AS BOOKINGNUM, $A$.CUSTOMER_ID_, $A$.EMAIL_ADDRESS_ FROM $A$ WHERE $A$.CUSTOMER_ID_ LIKE '%-1'
) $A$ ON $A$.BOOKING_LOCATOR = $A$.BOOKINGNUM

Quelqu'un peut-il me guider dans la bonne direction?


1 commentaires

Je nommerais la deuxième table comme $ B $ . Je suis surpris que votre SQL fonctionne même.


3 Réponses :


2
votes

Donnez un nom aux sous-sélections:

SELECT A.BOOKING_LOCATOR, B.CUSTOMER_ID_, B.EMAIL_ADDRESS_
FROM
(
  SELECT $A$.BOOKING_LOCATOR FROM $A$ WHERE ($A$.FIRST_NAME IN ('TBA', 'TBC', 'Tba', 'Tbc') OR $A$.FIRST_NAME IS NULL) AND $A$.POLAR_BOOKING_STATUS != 'C' AND $A$.BOOKING_STATUS != 'Waitlist' AND $A$.EMBARK_DATE >= SYSDATE+1
  GROUP BY $A$.BOOKING_LOCATOR
) A
INNER JOIN (
  SELECT $A$.BOOKING_LOCATOR AS BOOKINGNUM, $A$.CUSTOMER_ID_, $A$.EMAIL_ADDRESS_ FROM $A$ WHERE $A$.CUSTOMER_ID_ LIKE '%-1'
) B ON A.BOOKING_LOCATOR = B.BOOKINGNUM;


1 commentaires

Merci, Adder - cela a résolu mon problème - je ne peux pas croire que j'ai raté ça.



1
votes

YEAH, vous pouvez le faire. Vous pouvez soit utiliser des jointures, soit une demande externe pour cela.

SELECT A.BOOKING_LOCATOR, B.CUSTOMER_ID_, B.EMAIL_ADDRESS_
FROM
(
  SELECT $A$.BOOKING_LOCATOR FROM $A$ WHERE ($A$.FIRST_NAME IN ('TBA', 'TBC', 'Tba', 
 'Tbc') OR $A$.FIRST_NAME IS NULL) AND $A$.POLAR_BOOKING_STATUS != 'C' AND 
$A$.BOOKING_STATUS != 'Waitlist' AND $A$.EMBARK_DATE >= SYSDATE+1
 GROUP BY $A$.BOOKING_LOCATOR
) A
 Outer APPLY(
   SELECT $A$.BOOKING_LOCATOR AS BOOKINGNUM, $A$.CUSTOMER_ID_, $A$.EMAIL_ADDRESS_ FROM 
$A$ WHERE $A$.CUSTOMER_ID_ LIKE '%-1'
) B ON A.BOOKING_LOCATOR = B.BOOKINGNUM;

--2ND option consiste à utiliser OuterAPPLY.

SELECT A.BOOKING_LOCATOR, B.CUSTOMER_ID_, B.EMAIL_ADDRESS_
FROM
(
 SELECT $A$.BOOKING_LOCATOR FROM $A$ WHERE ($A$.FIRST_NAME IN ('TBA', 'TBC', 'Tba', 
'Tbc') OR $A$.FIRST_NAME IS NULL) AND $A$.POLAR_BOOKING_STATUS != 'C' AND 
$A$.BOOKING_STATUS != 'Waitlist' AND $A$.EMBARK_DATE >= SYSDATE+1
GROUP BY $A$.BOOKING_LOCATOR
) A
INNER JOIN (
SELECT $A$.BOOKING_LOCATOR AS BOOKINGNUM, $A$.CUSTOMER_ID_, $A$.EMAIL_ADDRESS_ FROM 
$A$ WHERE $A$.CUSTOMER_ID_ LIKE '%-1'
) B ON A.BOOKING_LOCATOR = B.BOOKINGNUM;


1 commentaires

Merci beaucoup pour votre solution, GraySkull. Comme ci-dessus, j'ai seulement voté Adder comme gagnant en raison de la réponse indiquant mon erreur.



1
votes

Si vous voulez que la réservation soit localisée et le client principal, alors EXISTS vient à l'esprit:

SELECT . . .   -- whatever columns you want
FROM $A$ a1
WHERE a.CUSTOMER_ID_ LIKE '%-1' AND
      EXISTS (SELECT 1
              FROM $A$ a
              WHERE a.FIRST_NAME IN ('TBA', 'TBC', 'Tba', 'Tbc') OR a.FIRST_NAME IS NULL) AND  
                    a.POLAR_BOOKING_STATUS <> 'C' AND  
                    a.BOOKING_STATUS <> 'Waitlist' AND  
                    a.EMBARK_DATE >= SYSDATE+1 AND
                    a.BOOKING_LOCATOR = a1.BOOKING_LOCATOR
              );

Cela ne renvoie qu'une seule ligne par client principal.


1 commentaires

Merci, Gordon - c'était une solution élégante, bien que difficile à saisir pour un débutant comme moi. Ça a marché. La seule raison pour laquelle je ne vous ai pas voté comme gagnant, c'est parce que Adder a souligné la simple erreur que j'ai faite dans mon code d'origine, fournissant une solution fonctionnelle.