Using ORDER BY on a multiple LEFT JOIN query - mysql

I have this long query that I finally got to work but I am unable to ORDER BY date_time_added, which is a field that is in all the tables except for user_accounts and relationships table. How do i make it work correctly?
$sql = "select distinct pb.user_id, pb.Full_name,
tv.why_onsite3, tv.onsite3_id, tv.other_date as onsite3_date,
tv.user_allowed as tv_user_allowed, np.onsite4_name ,
np.onsite4_id, np.other_date as onsite4_date, np.user_allowed
as np_user_allowed, pml.med_name , pml.med_id, pml.other_date
as pml_date, pml.user_allowed as pml_user_allowed, pl.onsite5_name,
pl.onsite5_test_id, pl.other_date as some_stats_date, pl.user_allowed as
pl_user_allowed, chlp.problem_name_is , chlp.current_problem_id,
chlp.other_date as chlp_date, chlp.user_allowed as chlp_user_allowed,
pphl.onsite10_health_prob_id , pphl.onsite10_problem_name_is,
pphl.other_date as pphl_date, pphl.user_allowed as pphl_user_allowed,
al.onsite_id , al.onsite_name, al.other_date as onsite_date,
al.user_allowed as al_user_allowed, sl.onsite2_id , sl.onsite2_name,
sl.other_date as onsite2_date, sl.user_allowed as sl_user_allowed,
hal.onsite6_id , hal.reason_for_admit, hal.other_date as hal_date,
hal.user_allowed as hal_user_allowed, il.onsite9_id , il.onsite9_name,
il.other_date as il_date , il.user_allowed as il_user_allowed
from user_accounts pb left join some_stuff tv on pb.user_id = tv.user_id
left join some_onsite4s np on pb.user_id = np.user_id
left join some_med pml on pb.user_id = pml.user_id
left join list_hal hal on pb.user_id = hal.user_id
left join list_for_things il on pb.user_id = il.user_id
left join list_on sl on pb.user_id = sl.user_id
left join some_all al on pb.user_id = al.user_id
left join some_list pphl on pb.user_id = pphl.user_id
left join some_stats pl on pb.user_id = pl.user_id
left join some_probs chlp on pb.user_id = chlp.user_id
where (pb.user_id in (select fb.friend_id from relationships fb
where fb.user_id = '$uid')
or pb.user_id in (select fb1.user_id from relationships fb1
where fb1.friend_id = '$uid')
)
group by pb.user_id ORDER BY date_time_added DESC LIMIT $startrow, 20";

In ORDER BY clause, you have to specify what is the exact column you are ordering by. That means you have to prefix the column that is used for ordering, because you have multiple columns that are called the same in multiple tables.
Other option is to restructure the query completely and use UNION operator with multiple SELECT statements. Each SELECT statement would pickup a group of data from one table and order that group by column from that table.
The solution depend on the data that you want to output - the context of the data.

Related

MYSQL Merge two columns from two tables and still use LEFT JOIN

So I'm having a slight problem with having to save price on a product in two different tables due to a few reasons. Is it possible to merge two columns into one? I know UNION exists but does it work with LEFT JOIN's?
Any pointers is much appreciated.
Best Regards
SELECT
si.id AS shop_item_id,
si.item_price,
s.logo_file_name,
p.cat_id AS category_id,
api.item_price AS api_price,
MAX(c.campaign_desc) AS campaignDesc,
MAX(c.campaign_type_id) AS campaignType,
MAX(c.shop_id) AS campaign_shop_id,
MAX(ct.image_name) AS campaignLogo
FROM
shop_item si
LEFT JOIN
shop s ON
s.id = si.shop_id
LEFT JOIN
product p ON
si.product_id = p.id
LEFT JOIN
campaign_category cc ON
cc.category_id = p.cat_id
LEFT JOIN
campaign c ON
c.id = cc.campaign_id AND
c.shop_id = si.shop_id AND
c.show_in_pricetable = 1 AND
NOW() BETWEEN c.date_from and c.date_to
LEFT JOIN
campaign_type ct ON
c.campaign_type_id = ct.id
LEFT JOIN
shop_api_item api ON
si.rel_feed_api = api.unique_id AND si.shop_id = api.shop_id
WHERE
si.`product_id` = 586 AND
s.`active_shop` = 1
GROUP BY
s.name,
si.id ,
si.item_price
ORDER BY
si.`item_price`,
si.`shop_id`,
c.`campaign_desc` DESC
It looks like you would benefit from the COALESCE() function.
SELECT
si.id AS shop_item_id,
COALESCE(si.item_price, api.item_price) AS coalesced_price,
...
COALESCE() takes multiple arguments, and returns the first argument that is not NULL.

mysql Fallback to another record if first not exist

I have two tables for creatives and its thumbnails. I want to query in a fallback way like:
Initially, the thumbnail will be displayed for 300x250
IF not available then 336x280,
IF not available then 300x600,
IF not available then 728x90,
IF not available then 160x600,
IF not available then 320x50,
IF not available then 300x50,
IF not available then 468x60
The table structure is like
creatives:
id INT
name VARCHAR
desc TEXT
creative_thumbs:
id
creative_id INT
dimension VARCHAR
img_url VARCHAR
I have made it with multiple joins (one for each dimension but it is a bit slow)
You can do this with a multiple LEFT JOIN query. It should be like:
SELECT
c.Name AS CreativeName,
COALESCE(
ct1.Dimension,
ct2.Dimension,
ct3.Dimension,
ct4.Dimension,
ct5.Dimension,
ct6.Dimension,
ct7.Dimension,
ct8.Dimension
) AS ThumbnailDimension
FROM creatives c
LEFT JOIN creative_thumbs ct1 ON c.id = ct1.creative_id AND ct1.Dimension = '300x250'
LEFT JOIN creative_thumbs ct2 ON c.id = ct2.creative_id AND ct2.Dimension = '336x280'
LEFT JOIN creative_thumbs ct3 ON c.id = ct3.creative_id AND ct3.Dimension = '300x600'
LEFT JOIN creative_thumbs ct4 ON c.id = ct4.creative_id AND ct4.Dimension = '728x90'
LEFT JOIN creative_thumbs ct5 ON c.id = ct5.creative_id AND ct5.Dimension = '160x600'
LEFT JOIN creative_thumbs ct6 ON c.id = ct6.creative_id AND ct6.Dimension = '320x50'
LEFT JOIN creative_thumbs ct7 ON c.id = ct7.creative_id AND ct7.Dimension = '300x50'
LEFT JOIN creative_thumbs ct8 ON c.id = ct8.creative_id AND ct8.Dimension = '468x60'
;
If this is too slow then try adding index to Dimension column:
CREATE INDEX creative_thumbs_Dimension_index
on creative_thumbs (Dimension);

How can i Get Better Time Result on This Mysql Query

i am Using This Mysql Query and is working Good, But i need go get a Better Time result. How can i do it?
SELECT TblExistencias.id as ID, TblExistencias.codigo as Codigo,
TblPartes.detalle as Detalle,TblPartes.neto1 as PrecioActual,
TblExistencias.Condicion_Producto as Condicion,TblCategorias.categoria as Categoria,
TblSubcategorias.subcategoria as Subcategoria, TblExistencias.costo as Costo,
TblExistencias.serial as Serial, TblExistencias.vendido as Vendido,
TblConceptosFacturas.ventaonline as VentaOnline, TblRemitos.nroremitocompleto as Remito,
TblFacturas.nrofacturacompleto as Factura, TblFacturas.fecha as FechaVenta,
TblConceptosFacturas.ventaTotUn as Venta,TblConceptosFacturas.comisionmlunit as Comision,
TblFacturas.costoenvio as Envio, if(TblExistencias.vendido =1,
TblConceptosFacturas.ventaTotUn - TblExistencias.Costo - TblConceptosFacturas.comisionmlunit - TblFacturas.costoenvio,0) as Ganancia,
TblProveedores.razonsocial as Proveedor, TblFacturasCompras.nrofacturacompleto as Compra,
TblFacturasCompras.fecha as FechaCompra, TblClientes.razonsocial as Cliente
from TblExistencias
left join TblPartes on TblExistencias.codigo = TblPartes.codigo1
left join TblRemitos on TblExistencias.id_RemitoVenta = TblRemitos.id
left join TblFacturasCompras on TblExistencias.id_factura = TblFacturasCompras.id
left join TblClientes on TblRemitos.id_cliente = TblClientes.id
left join TblFacturas on TblRemitos.id_factura = TblFacturas.id
left join TblConceptosFacturas on TblFacturas.id=TblConceptosFacturas.id_factura and TblConceptosFacturas.codigoproducto = TblExistencias.codigo
left join TblCategorias on TblCategorias.id = TblPartes.id_categoria
left join TblSubcategorias on TblPartes.id_subcategoria = TblSubcategorias.id
left join TblProveedores on TblFacturasCompras.id_proveedor = TblProveedores.id
order by comision desc
The solution is create an index on each relational columns, like:
TblFacturasCompras.id_proveedor = TblProveedores.id
Problem was in order clause, Query passed from 87 Secs to 4 Secs. Thanks for help.

slow query with joins

Please am having difficulty in optimizing this query. What am trying to achieve is to join about 8 tables, of which only about 3 of the tables contains large data (1.5m records). This query returns expected records but is taking 1min to run which is bad.
I know it can be optimized to perform far better, pls i need assistance from you experts. I have index on the fields used for join already.
SELECT topic_id,
topic_title,
unit_name_abbrev,
sch_name_abbrev,
picture_small_url AS thumbnail,
profile_pix_upload_path,
first_name,
last_name,
topic_poster,
topic_replies,
topic_views,
topic_last_post_time AS topic_post_time,
sch_sub_forum_id
FROM (_sch_forum_topics
INNER JOIN _users
ON ( _users.userid = _sch_forum_topics.topic_poster )
INNER JOIN _profile
ON _profile.userid = _users.userid
INNER JOIN _class
ON _users.classid = _class.classid
INNER JOIN _level
ON _class.level_id = _level.id
INNER JOIN _unit
ON _class.unitid = _unit.unitid
INNER JOIN _department
ON _unit.deptid = _department.deptid
INNER JOIN _faculty
ON _department.facid = _faculty.facid
INNER JOIN _university
ON _faculty.schid = _university.schid)
WHERE _sch_forum_topics.sch_sub_forum_id = 4
ORDER BY _sch_forum_topics.topic_last_post_time DESC
LIMIT 0, 15
Try to filter before making JOIN's.
SELECT topic_id,
topic_title,
unit_name_abbrev,
sch_name_abbrev,
picture_small_url AS thumbnail,
profile_pix_upload_path,
first_name,
last_name,
topic_poster,
topic_replies,
topic_views,
topic_last_post_time AS topic_post_time,
sch_sub_forum_id
FROM
( select * FROM sch_forum_topics WHERE sch_sub_forum_id = 4
ORDER BY topic_last_post_time DESC
LIMIT 0, 15 ) main
INNER JOIN _users
ON ( _users.userid = main.topic_poster )
INNER JOIN _profile
ON _profile.userid = _users.userid
INNER JOIN _class
ON _users.classid = _class.classid
INNER JOIN _level
ON _class.level_id = _level.id
INNER JOIN _unit
ON _class.unitid = _unit.unitid
INNER JOIN _department
ON _unit.deptid = _department.deptid
INNER JOIN _faculty
ON _department.facid = _faculty.facid
INNER JOIN _university
ON _faculty.schid = _university.schid);

mysql join and count

Somehow am not successful with creating the query that I want.
DB is to do with locations, there are the following tables which are relevant
t_location - list of locations incl. field t_location_zipcode, and t_location_id_location
t_zipcodecity - join table just t_zipcodecity_zipcode t_zipcodecity_id_city
t_city - city list with t_city_id_city
t_citystate - join table, t_citystate_id_city, t_citystate_id_state
t_state - list of states with t_state_id_state
Initially I tried to get a list of states with locations using this query:
SELECT DISTINCT `t_state_id_state`
, `t_state_name_full`
FROM (`t_state`)
LEFT JOIN `t_citystate` ON `t_state_id_state` = `t_citystate_id_state`
LEFT JOIN `t_city` ON `t_citystate_id_state` = `t_city_id_city`
LEFT JOIN `t_zipcodecity` ON `t_city_id_city` = `t_zipcodecity_id_city`
LEFT JOIN `t_location` ON `t_zipcodecity_zipcode` = `t_location_zipcode`
ORDER BY `t_state_name_full` asc ­
which works fine.
Now what I also need / want which I am failing dismally at is to get the number of locations in each state. I don't know if it can be done in this one query or if i need another, either way I need help!
you can use a count and a group by. Something like this:
SELECT DISTINCT `t_state_id_state`
, `t_state_name_full`
, COUNT(*)
FROM (`t_state`)
LEFT JOIN `t_citystate` ON `t_state_id_state` = `t_citystate_id_state`
LEFT JOIN `t_city` ON `t_citystate_id_state` = `t_city_id_city`
LEFT JOIN `t_zipcodecity` ON `t_city_id_city` = `t_zipcodecity_id_city`
LEFT JOIN `t_location` ON `t_zipcodecity_zipcode` = `t_location_zipcode`
GROUP BY `t_state_id_state` , `t_state_name_full`
ORDER BY `t_state_name_full` asc
SELECT t_state_id_state
, t_state_name_full
, COUNT(DISTINCT t_location_id_location) AS locations_number
FROM
t_state
LEFT JOIN
t_citystate ON t_state_id_state = t_citystate_id_state
LEFT JOIN
t_city ON t_citystate_id_state = t_city_id_city
LEFT JOIN
t_zipcodecity ON t_city_id_city = t_zipcodecity_id_city
LEFT JOIN
t_location ON t_zipcodecity_zipcode = t_location_zipcode
GROUP BY t_state_id_state
ORDER BY t_state_name_full ASC ­
Ok thats looking good, my bad with the left joins, i was initially trying to get ALL the states which is why i used them. But i change that to use inner joins
SELECT t_state_id_state,
t_state_name_full,
COUNT(DISTINCT t_location_id_location) AS locations_number
FROM t_state
INNER JOIN t_citystate ON t_citystate_id_state = t_state_id_state
INNER JOIN t_city ON t_city_id_city = t_citystate_id_city
INNER JOIN t_zipcodecity ON t_zipcodecity_id_city = t_city_id_city
INNER JOIN t_location ON t_location_zipcode = t_zipcodecity_zipcode
GROUP BY t_state_id_state
ORDER BY t_state_name_full ASC
then i actually end up with a result that looks good !