How to optimize this query to produce many comma spearate data? - php

This is my query:
SELECT
t1.vehicle_id vehicleId,
GROUP_CONCAT(distinct(t2.vehicle_name)) vehiclename,
t1.from_state_id fromStateId,
GROUP_CONCAT(distinct(t3.state_name)) fromState,
t1.to_state_id toStateId,
GROUP_CONCAT(distinct(t4.state_name)) toState,
t1.from_city_id fromCityId,
GROUP_CONCAT(distinct(t5.city_name)) fromCity,
t1.to_city_id toCitiesId,
GROUP_CONCAT(distinct(t6.city_name)) toCities
FROM
tbl_vendor_workstations as t1
LEFT JOIN
tbl_vehicles as t2
ON find_in_set(t2.id, t1.vehicle_id)
Left JOIN
tbl_states as t3
ON find_in_set(t3.id, t1.from_state_id)
Left JOIN
tbl_states as t4
ON find_in_set(t4.id, t1.to_state_id)
Left JOIN
tbl_city as t5
ON find_in_set(t5.id, t1.from_city_id)
Left JOIN
tbl_city as t6
ON find_in_set(t6.id, t1.to_city_id)
where
group by
t1.id ";
When I execute this query, it runs very slow. Does an alternative way exist to find many coma separate data?

You appear to have fields in the tbl_vendor_workstations which consist of comma separated lists of ids. This is a very bad idea. It stops the indexes being used effectively and also means that you have a limit on the list of values to hold for each item (ie, depending on the length of the field you are storing them in).
I would suggest you change your database to use link tables. Each of these would store the id of the row from tbl_vendor_workstations and the (for example) vehicle_id, with 1 row per combination. Hence one tbl_vendor_workstations.id might have dozens of rows on this table. You then join from tbl_vendor_workstations to the link table and then on to the tbl_vehicles to get the details of that vehicle.
CREATE TABLE tbl_vehicles_link
(
vendor_workstations_id INT(11),
vehicle_id INT(11),
PRIMARY KEY (`vendor_workstations_id`, `vehicle_id`),
KEY `vehicle_id` (`vehicle_id`),
);
Then your SQL would be something like this
SELECT t1.vehicle_id vehicleId,
GROUP_CONCAT(distinct(t2.vehicle_name)) vehiclename,
t1.from_state_id fromStateId,
GROUP_CONCAT(distinct(t3.state_name)) fromState,
t1.to_state_id toStateId,
GROUP_CONCAT(distinct(t4.state_name)) toState,
t1.from_city_id fromCityId,
GROUP_CONCAT(distinct(t5.city_name)) fromCity,
t1.to_city_id toCitiesId,
GROUP_CONCAT(distinct(t6.city_name)) toCities
FROM tbl_vendor_workstations as t1
LEFT OUTER JOIN tbl_vehicles_link as tl2 ON tl2.vendor_workstations_id = t1.id
LEFT OUTER JOIN tbl_vehicles as t2 ON t2.id = tl2.vehicle_id
LEFT OUTER JOIN tbl_states as tl3 ON tl3.vendor_workstations_id = t1.id
LEFT OUTER JOIN tbl_states as t3 ON t3.id = t1.from_state_id
LEFT OUTER JOIN tbl_states as tl4 ON tl4.vendor_workstations_id = t1.id
LEFT OUTER JOIN tbl_states as t4 ON t4.id = t1.to_state_id
LEFT OUTER JOIN tbl_city as tl5 ON tl5.vendor_workstations_id = t1.id
LEFT OUTER JOIN tbl_city as t5 ON t5.id = t1.from_city_id
LEFT OUTER JOIN tbl_city as tl6 ON tl6.vendor_workstations_id = t1.id
LEFT OUTER JOIN tbl_city as t6 ON t6.id = t1.to_city_id
WHERE t1.vendor_id=300 AND enterprise_user_id=68
GROUP BY t1.id

Related

COUNTING mysql table rows based on 2 conditions from another table

I have two tables table1 and table2. table1 has columns id and table2_id while table2 has id and category. I need to count rows from table1 based on two separate values in table2.category containing value Regular or Special.
I have done this in two queries but I want to know if it is possible in a single sql. My queries are:
"SELECT COUNT(t1.id) AS regular FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.t2_id = t2.id WHERE t2.category = 'Regular'";
"SELECT COUNT(t1.id) AS special FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.t2_id = pr.id WHERE t2.category = 'Special'";
Thanks.
EDIT
The second query JOIN should read ON t1.t2_id = t2.id and not ON t1.t2_id = pr.id. Sorry for the confusion that may have caused. Please update/edit your answers/comments accordingly.
Move the Where condition to CASE statement and do the counting
Here is one way using Conditional Aggregate
SELECT
COUNT(case when t2.category = 'Regular' then t1.id end) AS Regular,
COUNT(case when t2.category = 'Special' then t1.id end) AS special
FROM table1 t1
INNER JOIN table2 t2 ON t1.t2_id = pr.id
Where t2.category IN ('Regular','Special' )
Note : I have changed the LEFT JOIN to INNER JOIN because you want to count only when table2.category is 'Regular' or 'Special' so no use of LEFT JOIN here
Instead of
"SELECT COUNT(t1.id) AS regular FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.t2_id = t2.id WHERE t2.category = 'Regular'";
"SELECT COUNT(t1.id) AS special FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.t2_id = pr.id WHERE t2.category = 'Special'";
you can do this:
select t2.category, count(t1.id)
from table1 t1
left outer join table2
on t1.t2_id = t2.id
group by t2.category
having t2.category in ('Regular', 'Special')
The suggested query groups the joined records, filters the groups and selects the category name and its count.

left outer join when one field null

i have 3 tables t1,t2,t3 and its fields are given below
t1- t1id,name,age;
t2- t2id,t1id,date;
t3- t3id,t2id,time;
My Query is
select concat(t1.name,',',t2.date,',',t3.time)
from t1
left outer join t2 on t1.t1id=t2.t1id
left inner join t3 on t2.t2id=t3.t2id
where t1.age= 12
Some times t2id doesn't present in t3 table at that time i need result as name,date, how is it possible in a single Query?
You could use ifnull() to make concat() work even if some values are null
select concat(t1.name, ',', ifnull(it2.date, ''), ',', ifnull(t3.time,''))
from t1
left outer join t2 on t1.t1id=t2.t1id
left inner join t3 on t2.t2id=t3.t2id
where t1.age= 12
Of use CONCAT_WS()
select concat_ws(',', t1.name, it2.date, t3.time)
from t1
left outer join t2 on t1.t1id=t2.t1id
left inner join t3 on t2.t2id=t3.t2id
where t1.age= 12

Left Join 1 table to multiple tables in MYSQL

I have 4 tables, which are linked together with a foreign key from another, eg Table 2 has fk_table1, Table 3 has fk_table2, Table 4 has fk_table3.
The first 3 tables in this chain all have corresponding data for each entry. However, Table 4 contain optional data, therefore, there may not be a corresponding entry for a field in say Table 3.
But I want those data from Table 4 too. This is currently what I have, but doesn't work.
SELECT *
FROM T1, T2, T3 LEFT JOIN T4
WHERE T1.t1 = T2.t1
AND T2.t2 = T3.t2
AND T3.t3 = T4.t3
If only T4 is optional, use LEFT JOIN only on that table:
SELECT *
FROM T1
JOIN T2 ON T1.t1 = T2.t1
JOIN T3 ON T2.t2 = T3.t2
LEFT JOIN T4 ON T3.t3 = T4.t3
Try this:
SELECT *
FROM T1
LEFT JOIN T2 on T1.t1 = T2.t1
LEFT JOIN T3 on T2.t2 = T3.t2
LEFT JOIN T4 on T3.t3 = T4.t3
Update
Or if you want to only include rows where there is an appropriate row in T1, T2 or T3 you need to use an inner join.
SELECT *
FROM T1
INNER JOIN T2 on T1.t1 = T2.t1
INNER JOIN T3 on T2.t2 = T3.t2
LEFT JOIN T4 on T3.t3 = T4.t3
To separate the logic of table joins it's possible to use brackets:
select
*
from
t1
inner join t2 on t1.some_id = t2.some_id
inner join (
t3
left join t4 on t3.some_id = t4.some_id
) on t2.some_id = t3.some_id

What kind of JOIN should I use here?

I'm new to JOINS in MySql.
I have six tables: t1, t2, t3, t4, t5, t6.
And I also have one main table: main_table.
TOTAL 7 TABLES!
The first column of ALL tables is called classified_id.
If the user searches for "cars" then the main table will match everything in table t1 (which is the cars table) where classified_id is the same in both tables.
So:
SELECT * FROM main_table, t1 WHERE main_table.classified_id=t1.classified_id
This works fine, although I am not sure this is the way to join here. Performance is an issue in my case!
However, here is my problem.
Whenever ALL CLASSIFIEDS are searched, then I need to match the main_table.classified_id to the other tables classified_id column and get every classified there is.
How should this query be made up?
SELECT * FROM main_table, t1, t2, t3, t4, t5, t6 // I have this so far which is not much!
If you need more input just ask and I will update this Q.
Thanks
EDIT:
Table setup:
main_table: t1:
ID(PK) ID (PK)
classified_id -> 25 classified_id -> 25
category -> CARS year -> 1997
If the row would exist in all tables (i.e. every table has a row for a specific classified_id), then you would use an inner join:
SELECT
m.classified_id
,m.category
,t1.year
,........
FROM
main_table m
INNER JOIN t1 ON m.classified_id = t1.classified_id
INNER JOIN t2 ON m.classified_id = t2.classified_id
INNER JOIN t3 ON m.classified_id = t3.classified_id
INNER JOIN t4 ON m.classified_id = t4.classified_id
INNER JOIN t5 ON m.classified_id = t5.classified_id
INNER JOIN t6 ON m.classified_id = t6.classified_id
If the row does not exist in every table, then you'd use LEFT JOINS so that rows are not dropped
Use:
SELECT mt.*,
t1.*,
t2.*,
t3.*,
t4.*,
t5.*,
t6.*
FROM MAIN_TABLE mt
LEFT JOIN TABLE_1 t1 ON t1.classified_id = mt.classified_id
LEFT JOIN TABLE_2 t2 ON t2.classified_id = mt.classified_id
LEFT JOIN TABLE_3 t3 ON t3.classified_id = mt.classified_id
LEFT JOIN TABLE_4 t4 ON t4.classified_id = mt.classified_id
LEFT JOIN TABLE_5 t5 ON t5.classified_id = mt.classified_id
LEFT JOIN TABLE_6 t6 ON t6.classified_id = mt.classified_id
I used LEFT JOINs because if JOIN was used - records would be omitted that did not have a supporting record in at least one of the t1/2/3/4/5/6 tables. You might find this link helpful for understanding JOINs.

how do i join 7 tables where a column (which exists in all tables) equals the same content in all tables?

i have seen how to inner join 2 tables where a column is equal to the content in another column. but how do i do this with 7 tables?'
thanks everyone,
I figured it out lol after a long time. this seems to work
SELECT *
FROM
tbl_school
INNER JOIN tbl_apprequirments ON (tbl_school.schoolname = tbl_apprequirments.schoolname)
INNER JOIN tbl_citygallery ON (tbl_apprequirments.schoolname = tbl_citygallery.schoolname)
INNER JOIN tbl_schoolgallery ON (tbl_citygallery.schoolname = tbl_schoolgallery.schoolname)
INNER JOIN tbl_livingexp ON (tbl_schoolgallery.schoolname = tbl_livingexp.schoolname)
INNER JOIN tbl_tuition ON (tbl_livingexp.schoolname = tbl_tuition.schoolname)
where tbl_school.schoolname = 'glendale community college';
SELECT * FROM t1 JOIN t2 JOIN t3 JOIN t4 JOIN t5
ON (t2.c=t1.c AND t3.c=t1.c AND t4.c=t1.c AND t5.c=t1.c)
MySQL provides a shorthand for this:
SELECT * FROM t1 JOIN (t2, t3, t4, t5)
ON (t2.c=t1.c AND t3.c=t1.c AND t4.c=t1.c AND t5.c=t1.c)
This example is for 5 tables. You can repeat as necessary.
See MySQL's join syntax.
Edit: after seeing the clarification from sarmenhb, I think this query also works:
SELECT * FROM t1 JOIN (t2, t3, t4, t5, t6, t7)
USING (schoolname)
WHERE t1.schoolname = 'name'
After joining 2 of them, join the thrid to the first two, then the 4th to the first 3, etc,
Select *
From T1 Join T2 On <criteria>
Join T3, on <criteria>
Join T4 On <Criteria>
etc...
Try something like this...
Select data
from table as tbl1
join as tbl2 on tbl2.data = tbl1.data
join as tbl3 on tbl3.data = tbl1.data
is this what you are looking for?

Categories