SQL - Consulta compleja SQL

 
Vista:

Consulta compleja SQL

Publicado por Christian (1 intervención) el 01/06/2010 12:35:06
Hola a todos.

A ver si me podeis ayudar a realizar la siguiente consulta.
Tengo dos tablas: HEADER_TABLE and DETAILS_TABLE con una relación 1..N con la peculiaridad de que una cabecera puede ser que no tenga detalle.

*******************
HEADER_TABLE
********************

******************************
KEY * NAME1 * NAME2
******************************
KEY1 * Carlos * Abad
KEY2 * Albert * Garcia
KEY2 * Marc * Ingla
KEY2 * Isidre * Abait

******************
DETAILS_TABLE
*******************

**********************************************
KEY * POSITION
*********** **********************************
KEY1 * 01
KEY2 * 01
KEY2 * 02
KEY2 * 03
KEY3 * 01
KEY4 * 01
KEY4 * 02
KEY4 * 03

Yo con esta consulta:

SELECT A.KEY, A.NAME1, A.NAME2,'' AS POSITION
FROM HEADER_TABLE AS A LEFT JOIN DETAILS_TABLE AS B ON A.KEY = B.KEY

UNION

SELECT B.KEY,'' AS NAME1, '' AS NAME2, B.POSITION
FROM HEADER_TABLE AS A LEFT JOIN DETAILS_TABLE AS B ON A.KEY = B.KEY
WHERE (A.PI = '0')

ORDER BY A.KEY

Puedo obtener estos formateados de la siguiente manera. Un linea con los datos de cabecera y después n linea con sus detalles si los tiene.

****************************************
KEY * NAME1 * NAME2 * POSITION
****************************************
KEY1 * Carlos * Abad *
KEY2 * Albert * Garcia *
KEY2 * * * 01
KEY2 * * * 02
KEY2 * * * 03
KEY3 * Marc * Ingla *
KEY4 * Isidre * Abait *
KEY4 * * * 01
KEY4 * * * 02
KEY4 * * * 03

Si yo quisiera obtener el resultado formateado de la siguiente forma:

****************************************
KEY * NAME1 * NAME2 * POSITION
****************************************
KEY1 * Carlos * Abad *
KEY2 * Albert * Garcia * 01
KEY2 * * * 02
KEY2 * * * 03
KEY3 * Marc * Ingla *
KEY4 * Isidre * Abait * 01
KEY4 * * * 02
KEY4 * * * 03

Es decir, en la primer linea de cabecera, también los datos de la primera línea de detalle, como podría hacerlo?

Saludos y gracias
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil
Val: 806
Bronce
Ha mantenido su posición en SQL (en relación al último mes)
Gráfica de SQL

RE:Consulta compleja SQL

Publicado por Leonardo Josue (1173 intervenciones) el 01/06/2010 16:54:38
Buenos días Christian...

Antes que nada creo que en tus datos de ejemplo hay un error... en la table HEADER_TABLE creo que el campo Key para Marc Ingla debe ser KEY3 y para
Isidre Abait debe ser KEY4... ya que existen tres registros con la llave KEY2. (error de copy-paste)

Realmente no estabas tan errado con el query que pusiste... casi lo tenías, sólo era cuestión que la afinaras un poco más.

Te dejo cómo sería la consulta, pero primero te explico un poco como llegue a esta consulta. Lo primero que necesitas es hacer un left join entre tu tabla header y tu tabla detail. así:

SELECT A.key, A.name1, A.name2, b.position FROM header_table A LEFT JOIN detail_table b ON A.key = B.key

Esto de devuelve una tabla como esta:
Key|name1|name2|position|
KEY1|Carlos|Abad|01
KEY2|Albert|Garcia|01
KEY2|Albert|Garcia|02
KEY2|Albert|Garcia|03
KEY3|Isidre|Abait|01
KEY4|Marc|Ingla|01
KEY4|Marc|Ingla|02
KEY4|Marc|Ingla|03

Ahora bien, de esta tabla sólo necesitas el primer registro... por lo tanto lo único que hay que agregar es un filtro para que siempre tome la menor de las posiciones.

SELECT A.key, A.name1, A.name2, b.position FROM header_table A LEFT JOIN detail_table b ON A.key = B.key
WHERE b.position = (SELECT min(position) FROM detail_table C WHERE c.key = a.key)

de esta manera obtienes la siguiente tabla

KEY1|Carlos|Abad|01
KEY2|Albert|Garcia|01
KEY3|Isidre|Abait|01

Para obtener el resto la consulta sería prácticamente la misma, pero ahora te interesa excluir la primer posición, y no poner los campos nombre1 y nombre 2... por lo tanto sería más o menos así

SELECT A.key, '' as name1, '' as name2, B.position FROM header_table A LEFT JOIN detail_table b ON A.key = B.key
WHERE b.position != (SELECT min(position) FROM detail_table C WHERE c.llave = a.llave)

con esta consulta obtienes lo siguiente:

Key|name1|name2|position|
KEY2|||02
KEY2|||03
KEY4|||02
KEY4|||03

Finalmente sólo tienes que hacer la unión entre las dos subconsultas y ordenar tus campos para obtener el resultado esperado.

SELECT A.key, A.name1, A.name2, B.position FROM header_table A LEFT JOIN detail_table B ON A.key = B.key
WHERE B.position = (select min(C.position) from detail_table C WHERE C.key = A.key)
UNION
SELECT A.key,'' AS name1, '' AS name2, B.position
FROM header_table A LEFT JOIN detail_table B ON A.key = B.key
WHERE B.position != (SELECT min(position) FROM detail_table C WHERE C.key = A.key)
ORDER BY KEY, name1 desc, name2 desc, position

Saludos y espero tus comentarios.
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar