sql >> Database >  >> RDS >> Mysql

MySQL - Efficiënt combineren van twee select-statements in één resultaat met LIMIT

U kunt meerdere zoekopdrachten combineren met UNION , maar alleen als de query's hetzelfde aantal kolommen hebben. Idealiter zijn de kolommen hetzelfde, niet alleen in gegevenstype, maar ook in hun semantische betekenis; MySQL geeft echter niet om de semantiek en zal verschillende datatypes afhandelen door iets meer generiek te casten - dus indien nodig zou overbelast de kolommen om verschillende betekenissen van elke tabel te hebben en bepaal vervolgens welke betekenis geschikt is in uw code op een hoger niveau (hoewel ik het niet aanraad om het op deze manier te doen).

Als het aantal kolommen verschilt, of als u een betere/minder overbelaste uitlijning van gegevens van twee query's wilt bereiken, kunt u dummy letterlijke kolommen invoegen in uw SELECT verklaringen. Bijvoorbeeld:

SELECT t.cola, t.colb, NULL, t.colc, NULL FROM t;

U kunt zelfs enkele kolommen reserveren voor de eerste tabel en andere voor de tweede tabel, zodat ze NULL zijn elders (maar onthoud dat de kolomnamen uit de eerste zoekopdracht komen, dus u kunt ervoor zorgen dat ze daar allemaal worden genoemd):

  SELECT a, b, c, d, NULL AS e, NULL AS f, NULL AS g FROM t1
UNION ALL -- specify ALL because default is DISTINCT, which is wasted here
  SELECT NULL, NULL, NULL, NULL, a, b, c FROM t2;

U kunt proberen uw twee zoekopdrachten op deze manier op elkaar af te stemmen en ze vervolgens te combineren met een UNION exploitant; door LIMIT toe te passen naar de UNION , je hebt je doel bijna bereikt:

  (SELECT ...)
UNION
  (SELECT ...)
LIMIT 10;

Het enige probleem dat overblijft is dat, zoals hierboven weergegeven, 10 of meer records uit de eerste tabel alle records uit de tweede zullen "duwen". We kunnen echter een ORDER BY . gebruiken in de buitenste vraag om dit op te lossen.

Alles bij elkaar:

(
  SELECT
    dr.request_time AS event_time, m.member_name,      -- shared columns
    dr.request_id, dr.member1, dr.member2,             -- request-only columns
    NULL AS alert_id, NULL AS alerter_id,              -- alert-only columns
      NULL AS alertee_id, NULL AS type
  FROM dating_requests dr JOIN members m ON dr.member1=m.member_id 
  WHERE dr.member2=:loggedin_id
  ORDER BY event_time LIMIT 10 -- save ourselves performing excessive UNION
) UNION ALL (
  SELECT
    da.alert_time AS event_time, m.member_name,        -- shared columns
    NULL, NULL, NULL,                                  -- request-only columns
    da.alert_id, da.alerter_id, da.alertee_id, da.type -- alert-only columns
  FROM
    dating_alerts da
    JOIN dating_alerts_status das USING (alert_id, alertee_id)
    JOIN members m ON da.alerter_id=m.member_id
  WHERE
    da.alertee_id=:loggedin_id
    AND da.type='platonic'
    AND das.viewed='0'
    AND das.viewed_time<da.alert_time
  ORDER BY event_time LIMIT 10 -- save ourselves performing excessive UNION
)
ORDER BY event_time
LIMIT 10;

Natuurlijk is het nu aan jou om te bepalen met welk type rij je te maken hebt terwijl je elke record in de resultatenset leest (stel voor dat je request_id test en/of alert_id voor NULL waarden; als alternatief zou men een extra kolom aan de resultaten kunnen toevoegen die expliciet vermeldt uit welke tabel elk record afkomstig is, maar het zou equivalent moeten zijn op voorwaarde dat die id kolommen zijn NOT NULL ).




  1. pg gem installeren; FOUT:kan de native extensie van de edelsteen niet bouwen

  2. Postgresql:tabelnaam / schemaverwarring

  3. MySQL crasht op SQL

  4. Meerdere relaties tussen twee entiteiten, is dit een goede gewoonte?