web-dev-qa-db-fra.com

Jointure interne conditionnelle

Je veux pouvoir joindre en interne deux tables basées sur le résultat d'une expression.

Ce que j'ai essayé jusqu'à présent:

INNER JOIN CASE WHEN RegT.Type = 1 THEN TimeRegistration ELSE DrivingRegistration AS RReg
ON
RReg.RegistreringsId = R.Id

RegT est une jointure que j'ai faite juste avant cette jointure:

INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id

Ce script SQL ne fonctionne pas.

Donc dans l’ensemble, si la variable Type est 1, elle devrait être jointe à la table TimeRegistration sinon elle devrait être jointe à DrivingRegistration.

Solution:

Dans mon instruction select, j'ai effectué les jointures suivantes:

INNER JOIN  RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id
LEFT OUTER JOIN TimeRegistration AS TReg ON TReg.RegistreringsId = R.Id AND RegT.Type = 1
LEFT OUTER JOIN DrivingRegistration AS DReg ON DReg.RegistreringsId = R.Id AND RegT.Type <>1

Ensuite, j'ai édité mon where-clause pour afficher le correct, en fonction de la RegType, comme ceci:

WHERE (CASE RegT.Type WHEN 1 THEN TReg.RegistreringsId ELSE DReg.RegistreringsId END = R.Id)
22
KristianB

Essayez de mettre les deux tables dans la requête en utilisant LEFT JOIN

LEFT JOIN TimeRegistration TR ON r.rid = TR.Id AND RegT.type =1 
LEFT JOIN DrivingRegistration DR ON r.rid = DR.Id AND RegT.type <>1 

Maintenant, dans votre clause de sélection, utilisez

CASE RegType.Type WHEN 1 THEN TR.SomeField ELSE DR.someField END as SomeField

L'autre option consiste à utiliser du SQL dynamique

19
Sparky

Vous devez probablement effectuer deux jointures à gauche, une sur TimeRegistration et une sur DrivingRegistration, puis renvoyer les champs souhaités à partir de la table de jointure appropriée, comme suit:

LEFT JOIN TimeRegistration ON TimeRegistration.RegistreringsId = R.Id
LEFT JOIN DrivingRegistration ON DrivingRegistration.RegistreringsId = R.Id

et vous sélectionnez la déclaration serait quelque chose comme ça:

SELECT CASE WHEN RegT.Type = 1 THEN TimeRegistration.Foo ELSE DrivingRegistration.Bar END

J'aime ce que vous essayez de faire, mais je ne pense pas que SQL est aussi intelligent.

8
David
SELECT
  R.foo, tr.bar
FROM
  SomeTable AS R
  INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id 
                                          AND RegT1.Type = 1
  INNER JOIN TimeRegistration AS tr    ON /* whatever */

UNION 

SELECT
  R.foo, dr.bar
FROM
  SomeTable AS R
  INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id 
                                          AND RegT1.Type = 2
  INNER JOIN DrivingRegistration AS dr ON /* whatever */
1
Tomalak

J'ai donc eu un scénario où il y avait trois colonnes d'email dans une table (ne demandez pas pourquoi) et n'importe laquelle d'entre elles pourrait être nulle (ou vide). Dans cet exemple de code, je traiterai simplement d'un cas où il est nul.

Je devais le joindre à une autre table par n'importe lequel des courriels pour récupérer le prénom de l'utilisateur.

Voici ce qui a fonctionné

select  

m.email1,
m.email2,
m.email3, 
m2.firstName

from MyTable m

left join MyOtherTable m2 on m2.Email = 
case when m.email1 is null then 

    case when m.email2 is null then 

        case when m.email3 null then 
            '[email protected]' -- i stopped here
        else m.email3 end

    else wm.email2 end

else m.email1 end

Évidemment, vous incluriez d’autres conditions telles que

case when m.email1 is null or m.email1 = '' then ...

Pour couvrir les valeurs vides.

0
ozzy432836