SQL - Obtener sólo el primer resultado con join

   
Vista:

Obtener sólo el primer resultado con join

Publicado por José Manuel (7 intervenciones) el 11/01/2014 15:21:21
Hola.

Lo primero, aviso que soy novato en esto del sql, pero con vuestra ayuda he creado la siguiente
consulta en MySQL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
select distinctrow
	ORDERS.reference as 'REFERENCIA',
	ORDERS.current_state as 'STATUS',
	ORDERS.invoice_date as 'FECHA_PAGO',
	CARRIER.name as 'TRANSPORTE',
	ADDRESS_F.firstname as 'NOMBRE_F',
	ADDRESS_F.lastname as 'APELLIDO_F',
	ADDRESS_F.address1 as 'DIRECCION_F1',
	ADDRESS_F.address2 as 'DIRECCION_F2',
	ADDRESS_F.postcode as 'CP_F',
	ADDRESS_F.city as 'LOCALIDAD_F',
	STATE_F.name as 'PROVINCIA_F',
	STATE_F.iso_code as 'COD_PROV_F',
	COUNTRY_LANG_F.name as 'PAIS_F',
	COUNTRY_F.iso_code as 'COD_PAIS_F',
	ADDRESS_D.firstname as 'NOMBRE_D',
	ADDRESS_D.lastname as 'APELLIDO_D',
	ADDRESS_D.address1 as 'DIRECCION_D1',
	ADDRESS_D.address2 as 'DIRECCION_D2',
	ADDRESS_D.postcode as 'CP_D',
	ADDRESS_D.city as 'LOCALIDAD_D',
	STATE_D.name as 'PROVINCIA_D',
	STATE_D.iso_code as 'COD_PROV_D',
	COUNTRY_LANG_D.name as 'PAIS_D',
	COUNTRY_D.iso_code as 'COD_PAIS_D',
	ORDERS.gift as 'REGALO',
	ORDERS.gift_message as 'MENSAJE_REGALO',
	ORDER_CARRIER.weight as 'PESO',
	ORDER_INVOICE.total_discount_tax_incl as 'DESCUENTO',
	ORDER_INVOICE.total_shipping_tax_incl as 'PRECIO_TRANSPORTE',
	ADDRESS_F.company as 'EMPRESA_F',
	ADDRESS_D.company as 'EMPRESA_D',
	MESSAGE.message as 'MENSAJE_PEDIDO',
	ORDERS.invoice_number as 'NUM_FRA'
from
	ps_orders as ORDERS
	left join ps_carrier as CARRIER on CARRIER.id_carrier = ORDERS.id_carrier
	left join ps_address as ADDRESS_F on ADDRESS_F.id_address = ORDERS.id_address_invoice
	left join ps_state as STATE_F on STATE_F.id_state = ADDRESS_F.id_state
	left join ps_country_lang as COUNTRY_LANG_F on COUNTRY_LANG_F.id_country = ADDRESS_F.id_country
	left join ps_country as COUNTRY_F on COUNTRY_F.id_country = ADDRESS_F.id_country
	left join ps_address as ADDRESS_D on ADDRESS_D.id_address = ORDERS.id_address_delivery
	left join ps_state as STATE_D on STATE_D.id_state = ADDRESS_D.id_state
	left join ps_country_lang as COUNTRY_LANG_D on COUNTRY_LANG_D.id_country = ADDRESS_D.id_country
	left join ps_country as COUNTRY_D on COUNTRY_D.id_country = ADDRESS_D.id_country
	left join ps_order_carrier as ORDER_CARRIER on ORDER_CARRIER.id_order = ORDERS.id_order
	left join ps_order_invoice as ORDER_INVOICE on ORDER_INVOICE.id_order = ORDERS.id_order
	left join ps_message as MESSAGE on MESSAGE.id_order = ORDERS.id_order
where
	((ORDERS.invoice_number >= 0) and (ORDERS.invoice_number <= 120))
order by
	ORDERS.reference

La consulta sirve para obtener unos cuantos datos sobre los pedidos en una tienda Prestashop.
La he puesto entera, pero mi duda se centra en el último campo del SELECT, y el penúltimo LEFT JOIN del FROM.

Me explico:
La tabla ps_message contiene un campo id_order que la relaciona con la tabla ps_orders (que también contiene un campo id_order).
En la tabla ps_orders, el campo id_order es una clave primaria, y no puede repetirse, pero en la tabla ps_message, puede haber varios registros con el mismo id_order (como ya supondreis, se trataría de varios mensajes asociados a un mismo pedido).

Lo que quiero es que la consulta me saque sólo cada pedido con el primer mensaje asociado a él.

Sería algo así como poner un LIMIT 1 al último LEFT JOIN, pero evidentemente esto no se puede hacer. He intentado mil cosas, pero no doy con la tecla.

¿Alguna idea de como hacerlo?

Muchas 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
Imágen de perfil de xve

Obtener sólo el primer resultado con join

Publicado por xve (238 intervenciones) el 12/01/2014 19:13:16
Hola José Manuel, la verdad es que la consulta es muy extensa, y no se muy bien los valores que devuelve, pero te podría servir vincular el ultimo left join con una consulta?? algo así:

1
left join (SELECT * FROM ps_message ORDER BY ... LIMIT 1) as MESSAGE on MESSAGE.id_order = ORDERS.id_order

Coméntanos, ok?
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

Obtener sólo el primer resultado con join

Publicado por José Manuel (7 intervenciones) el 16/01/2014 11:43:04
Gracias xve.

Perdona que haya tardado en responder. Como me has dicho no funciona, me saca todos los resultados con el campo MENSAJE_PEDIDO = null.

Tal como tú lo has puesto, si no lo entiendo mal, la subconsulta va a obtener siempre un sólo registro de la tabla ps_message, concretamente el que corresponda al ORDER BY, independientemente de la condición que hay fuera de la subconsulta.

Entonces, sólo por casualidad podría ocurrir que en algún caso se cumpla la condición que hay a continuación, con lo que en los resultados de la consulta principal, el campo MENSAJE_PEDIDO no tiene valor.

Con la idea que me has dado incluir una subconsulta en el JOIN, he estado intentando diversas cosas, pero tampoco he conseguido nada.

En realidad, creo que el problema se reduce a conseguir que la subconsulta me devuelva una tabla con los registros de la tabla ps_message, pero con la condición de que cuando haya varios registros con el mismo valor en el campo id_order, me saque sólo el que tenga el valor más pequeño en el campo id_message.

Pero tampoco sé como hacerlo.
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

Obtener sólo el primer resultado con join

Publicado por José Manuel (7 intervenciones) el 17/01/2014 14:09:04
Al final, buscando y buscando he encontrado lo que necesitaba.

Por si a alguien le sirve, la solución fué utilizar una subconsulta dentro de otra, y lo más importante, utilizar GROUP BY id_order, para que la subconsulta no repita registros con el mismo nº de pedido.

La consulta ha quedado así (cambian el penúltimo campo del SELECT y el último JOIN):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
SELECT DISTINCTROW
	ORDERS.reference AS 'REFERENCIA',
	ORDERS.current_state AS 'STATUS',
	ORDERS.invoice_date AS 'FECHA_PAGO',
	CARRIER.name AS 'TRANSPORTE',
	ADDRESS_F.firstname AS 'NOMBRE_F',
	ADDRESS_F.lAStname AS 'APELLIDO_F',
	ADDRESS_F.address1 AS 'DIRECCION_F1',
	ADDRESS_F.address2 AS 'DIRECCION_F2',
	ADDRESS_F.postcode AS 'CP_F',
	ADDRESS_F.city AS 'LOCALIDAD_F',
	STATE_F.name AS 'PROVINCIA_F',
	STATE_F.iso_code AS 'COD_PROV_F',
	COUNTRY_LANG_F.name AS 'PAIS_F',
	COUNTRY_F.iso_code AS 'COD_PAIS_F',
	ADDRESS_D.firstname AS 'NOMBRE_D',
	ADDRESS_D.lAStname AS 'APELLIDO_D',
	ADDRESS_D.address1 AS 'DIRECCION_D1',
	ADDRESS_D.address2 AS 'DIRECCION_D2',
	ADDRESS_D.postcode AS 'CP_D',
	ADDRESS_D.city AS 'LOCALIDAD_D',
	STATE_D.name AS 'PROVINCIA_D',
	STATE_D.iso_code AS 'COD_PROV_D',
	COUNTRY_LANG_D.name AS 'PAIS_D',
	COUNTRY_D.iso_code AS 'COD_PAIS_D',
	ORDERS.gift AS 'REGALO',
	ORDERS.gift_message AS 'MENSAJE_REGALO',
	ORDER_CARRIER.weight AS 'PESO',
	ORDER_INVOICE.total_discount_tax_incl AS 'DESCUENTO',
	ORDER_INVOICE.total_shipping_tax_incl AS 'PRECIO_TRANSPORTE',
	ADDRESS_F.company AS 'EMPRESA_F',
	ADDRESS_D.company AS 'EMPRESA_D',
	MENSAJES.message AS 'MENSAJE_PEDIDO',
	ORDERS.invoice_number AS 'NUM_FRA'
FROM
        ps_orders AS ORDERS
	LEFT JOIN ps_carrier AS CARRIER ON CARRIER.id_carrier = ORDERS.id_carrier
	LEFT JOIN ps_address AS ADDRESS_F ON ADDRESS_F.id_address = ORDERS.id_address_invoice
	LEFT JOIN ps_state AS STATE_F ON STATE_F.id_state = ADDRESS_F.id_state
	LEFT JOIN ps_country_lang AS COUNTRY_LANG_F ON COUNTRY_LANG_F.id_country = ADDRESS_F.id_country
	LEFT JOIN ps_country AS COUNTRY_F ON COUNTRY_F.id_country = ADDRESS_F.id_country
	LEFT JOIN ps_address AS ADDRESS_D ON ADDRESS_D.id_address = ORDERS.id_address_delivery
	LEFT JOIN ps_state AS STATE_D ON STATE_D.id_state = ADDRESS_D.id_state
	LEFT JOIN ps_country_lang AS COUNTRY_LANG_D ON COUNTRY_LANG_D.id_country = ADDRESS_D.id_country
	LEFT JOIN ps_country AS COUNTRY_D ON COUNTRY_D.id_country = ADDRESS_D.id_country
	LEFT JOIN ps_order_carrier AS ORDER_CARRIER ON ORDER_CARRIER.id_order = ORDERS.id_order
	LEFT JOIN ps_order_invoice AS ORDER_INVOICE ON ORDER_INVOICE.id_order = ORDERS.id_order
	LEFT JOIN (
		SELECT *
		FROM (
			SELECT *
			FROM ps_message
			ORDER BY id_message ASC
			) AS tmp GROUP BY id_order
		) AS MENSAJES ON MENSAJES.id_order = orders.id_order
WHERE
        (ORDERS.invoice_number >= 0) AND (ORDERS.invoice_number <= 120)
ORDER BY
        ORDERS.reference
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de xve

Obtener sólo el primer resultado con join

Publicado por xve (238 intervenciones) el 17/01/2014 15:48:03
Gracias por comentarlo José!!!
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