Mysql-vakbonden op dezelfde set samengevoegde tabellen

Dus mijn excuses als dit al eerder is gebeurd, maar ik kon geen goed antwoord vinden.

Ik probeer een enkele kolom met ID's uit een reeks van 3 kolommen in mijn tabel te krijgen die is gekoppeld aan een andere tabel.

De select-instructie om een ​​enkele kolom te krijgen, zou als volgt zijn:

SELECT id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue = X;

Nu ik het begrijp, kan ik vakbonden doen om deze als volgt te krijgen:

SELECT spec_id1 AS id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue1 = X
UNION
SELECT spec_id2 AS id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue2 = Y
UNION
SELECT spec_id3 AS id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue3 = Z

Is er een manier om TableA JOIN-tabelB opnieuw te gebruiken GEBRUIKSAANWIJZING (toets 1, toets 2), zodat deze niet wordt samengevoegd voor elke select? Ik heb ook een WHERE-voorwaarde die van toepassing is op alle selecties die hierboven niet worden weergegeven. Kan ik mogelijk iets hergebruiken als:

FROM TableA JOIN TableB USING (key1, key2) WHERE someOtherValue = W

Ik probeer dit in PHP te doen met mysqli. Mijn oorspronkelijke instinct was om een ​​tijdelijke tabel te gebruiken en daarnaar te vragen, maar ik weet niet zeker hoe ik dat in mysqli moet aanpakken. Als ik de tabel voor meerdere volgende query's kan gebruiken, is dit dubbel ideaal, omdat er extra gegevens in de gekoppelde tabellen staan ​​die later kunnen worden gebruikt.

Sorry als dit naïef is, maar ik ben niet echt een grote webontwikkelaar. Bij voorbaat dank.

BEWERK: Ik ben aan het kijken naar tijdelijke tafels, en het lijkt erop dat dit een goede manier is om het te omringen. Ik zou nog steeds een bevestiging willen hebben of het een goed idee is of niet, voordat ik er iets mee doe.

1
U kunt een CASE -instructie proberen: dev.mysql.com/doc/refman/5.0/en/… hoewel ik niet helemaal zeker weet hoe nuttig dat in uw situatie zal zijn. Ik zie wat je probeert te doen, maar als je die kolommen samen combineert, hoe ga je dan vertellen welke waarde uit welke kolom kwam?
toegevoegd de auteur sgcharlie, de bron
Ah, gotcha. Ja, ik zou een CASE -instructie met een gecombineerde WHERE -clausule voorstellen, als je echt je hart hebt ingesteld op het uitvoeren van slechts één query.
toegevoegd de auteur sgcharlie, de bron
Het kan me niet schelen van welke kolom het afkomstig is. Om u een concreter voorbeeld te geven van wat ik aan het doen zijn, lijken de 3 kolommen op manager-id, coördinator-id en supervisor-id. Elk is een duidelijk andere rol, ook al lijkt het er misschien niet op. Ik ben bezig met het verzenden van allemaal een soortgelijke e-mail die slechts een algemene e-mail van het managementtype is. Ongeacht hun exacte positie krijgen ze dezelfde e-mail, dus ondanks dat ze 3 verschillende kolommen hebben die om andere redenen nodig zijn, krijgen ze allemaal dezelfde e-mail.
toegevoegd de auteur Mic Rooney, de bron

2 antwoord

Er is geen snelkoppeling - niet zonder het ontwerp van de tafel te veranderen. Uw aanpak is solide en u moet zich geen zorgen maken over het hebben van 3 joins in uw zoekopdracht.

Als bekend is dat de 3 lijsten met spec_ids geen overlappende waarden bevatten, kunt u de prestaties verbeteren door UNION in UNION ALL te wijzigen.


Een mogelijke herschrijving, zonder het algemene UNION -plan te wijzigen, is om joins in EXISTS subqueries te wijzigen:

    SELECT spec_id1 AS id 
    FROM TableA 
    WHERE EXISTS
          ( SELECT * 
            FROM TableB 
            WHERE (TableB.key1, TableB.key2) = (TableA.key1, TableA.key2)
              AND someValue1 = X
          )
UNION                --- or UNION ALL
    ...
UNION
    ...

of - als de spec_ids allemaal zijn opgenomen in een andere BaseTable - kunt u zoiets hebben dat een beter uitvoeringsplan oplevert:

SELECT id
FROM BaseTable
WHERE EXISTS
      ( SELECT * AS id 
        FROM TableA 
          JOIN TableB 
            USING (key1, key2) 
        WHERE someValue1
          AND TableA.spec_id1 = BaseTable.id
      )
    OR EXISTS
       ( 
       ...
       )
    OR ...
1
toegevoegd
Ik denk dat de eerste, maar de beste zou zijn om het te testen (met uw gegevens). En u moet proberen de drie subquery's afzonderlijk te optimaliseren als u de UNION ALL kunt gebruiken.
toegevoegd de auteur ypercubeᵀᴹ, de bron
Als er overlappende waarden zouden kunnen zijn in elk van de 3 lijsten, maar niet tussen de 3 lijsten zou het goedkoper zijn om SELECT DISTINCT te doen met UNION ALL of om SELECT te doen met UNION (niet onderscheiden of alles)?
toegevoegd de auteur Mic Rooney, de bron
Dat klopt :-p Om een ​​of andere reden probeer ik altijd te optimaliseren en probeer het dan. Ik ben niet gewend aan webontwikkeling waar de meeste dingen onmiddellijk kunnen worden getest. ;)
toegevoegd de auteur Mic Rooney, de bron

Probeer de CASE-verklaring. Je zou het zonder de UNION moeten kunnen doen

SELECT 
    CASE 
        WHEN someValue1 = X THEN spec_id1 
        WHEN someValue2 = Y THEN spec_id2 
        WHEN someValue3 = Z THEN spec_id3 
    END
 AS id FROM TableA JOIN TableB USING (key1, key2) 
WHERE 
someValue1 = X OR someValue2 = Y OR WHERE someValue3 = Z
1
toegevoegd