2010-07-02 23 views
5

Estoy usando SQL Server 2008 y tengo 3 tablas, x, y y z. y existe para crear una relación de varios a varios entre x y z.Valor máximo en una relación muchos a muchos

x  y  z 
--  --  -- 
id xid  id 
     zid sort 

Todos los campos anteriores son int.

Quiero encontrar el método de mejor rendimiento (excluyendo desnormalizar) de encontrar el z con la más alta para cualquier sortx, y devolver todos los campos de las tres tablas.

datos de la muestra:

x: id 
    -- 
     1 
     2 

y: xid zid 
    --- --- 
     1 1 
     1 2 
     1 3 
     2 2 

z: id sort 
    -- ---- 
    1 5 
    2 10 
    3 25 

conjunto de resultados debe ser

xid zid 
--- --- 
    1 3 
    2 2 

Tenga en cuenta que si más de un z existe con el mismo valor más alto sort, entonces yo todavía sólo quiero una fila por x.

Tenga en cuenta también que en mi situación del mundo real, hay otros campos en las tres tablas que necesitaré en mi conjunto de resultados.

+0

supongo que usted está después de la solución de la situación del mundo real? Le sugiero que actualice su pregunta con un par de campos adicionales para cada tabla, y defina lo que le gustaría que buscara su conjunto de resultados. – MPritchard

+0

Solo para agregar a esta pregunta. ¿Su diseño de base de datos está reparado o todavía se está implementando? Me parece extraño que tu "clasificación" esté en la tabla z y no en la tabla y. Por lo general, encuentro que una relación de muchos a muchos como este a menudo tiene el tipo de "z" que podría interesarle en la tabla "y". Ignorarme si estoy equivocado, es imposible saberlo sin contexto. –

+0

Todavía se está implementando y estoy de acuerdo con lo que dices, pero en el contexto de lo que se está creando, el género está y debe estar en la tabla 'z'. – enashnash

Respuesta

0

Un método es con una consulta sub. Sin embargo, esto solo es bueno para obtener el ID de Z. Si necesita más/todas las columnas de ambas tablas x y z, esta no es la mejor solución.

SELECT 
    x.id, 
    (
     SELECT TOP 1 
      z.zid 
     FROM 
      y 
     INNER JOIN 
      z 
     ON 
      z.id = y.zid 
     WHERE 
      y.xid = x.id 
     ORDER BY 
      z.sort DESC 
    ) 
FROM 
    x 

Así es como puede hacerlo y devolver todos los datos de todas las tablas.

SELECT 
    * 
FROM 
    x 
INNER JOIN 
    y 
ON 
    y.xid = x.id 
AND 
    y.zid = 
(
    SELECT TOP 1 
     z2.zid 
    FROM 
     y y2 
    INNER JOIN 
     z z2 
    ON 
     z2.id = y2.zid 
    WHERE 
     y2.xid = x.id 
    ORDER BY 
     z2.sort DESC 
) 
INNER JOIN 
    z 
ON 
    z.id = y.zid 
+0

aclarado en la pregunta – enashnash

+0

editado para incluir todos los datos –

+0

Acabo de comparar esto con la solución proporcionada por el arácnido y salió un 8% más rápido en mi contexto. – enashnash

0
select xid,max(zid) as zid from y 
group by xid 
+0

el máximo debe estar en "ordenar" no en zid. por lo tanto, esto no funciona –

0
select xid, zid /* columns from x; and columns from y or z taken from q */ 
from (select y.xid, y.zid, /* columns from y or z */ 
      row_number() over(partition by y.xid order by z.sort desc) r 
     from y 
      join z on z.id = y.zid 
    ) q 
    join x on x.id = q.xid 
where r = 1 
+0

Creo que esto es lo que estoy buscando. Puedo agregar columnas adicionales a la selección interna y luego seleccionarlas en la externa para obtener todas las columnas en las tres tablas. Ahora solo necesito saber si esta es la mejor manera de hacerlo. – enashnash

Cuestiones relacionadas