sql >> Base de Datos >  >> RDS >> Mysql

MySQL:combinación de dos declaraciones de selección en un resultado con LIMIT de manera eficiente

Puede combinar múltiples consultas con UNION , pero solo si las consultas tienen el mismo número de columnas. Idealmente, las columnas son las mismas, no solo en el tipo de datos, sino también en su significado semántico; sin embargo, MySQL no se preocupa por la semántica y manejará diferentes tipos de datos convirtiéndolos en algo más genérico, por lo que, si es necesario, podría sobrecargue las columnas para que tengan diferentes significados de cada tabla, luego determine qué significado es apropiado en su código de nivel superior (aunque no recomiendo hacerlo de esta manera).

Cuando el número de columnas difiere, o cuando desea lograr una alineación de datos mejor o menos sobrecargada de dos consultas, puede insertar columnas literales ficticias en su SELECT declaraciones. Por ejemplo:

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

Incluso podría tener algunas columnas reservadas para la primera tabla y otras para la segunda tabla, de modo que sean NULL en otro lugar (pero recuerde que los nombres de las columnas provienen de la primera consulta, por lo que es posible que desee asegurarse de que todos estén nombrados allí):

  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;

Podría intentar alinear sus dos consultas de esta manera y luego combinarlas con una UNION operador; aplicando LIMIT a la UNION , estás cerca de lograr tu objetivo:

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

El único problema que queda es que, como se presentó anteriormente, 10 o más registros de la primera tabla "empujarán" cualquier registro de la segunda. Sin embargo, podemos utilizar un ORDER BY en la consulta externa para resolver esto.

Poniendo todo junto:

(
  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;

Por supuesto, ahora depende de usted determinar con qué tipo de fila está tratando a medida que lee cada registro en el conjunto de resultados (le sugerimos que pruebe request_id y/o alert_id para NULL valores; alternativamente, se podría agregar una columna adicional a los resultados que indique explícitamente de qué tabla se originó cada registro, pero debería ser equivalente siempre que esos id las columnas son NOT NULL ).