How to Optimize my JOIN's to speed up my Query? - mysql

I have 6 queries like the following query listed below..
each are taking 6 seconds to run
for a total of 36 seconds for page to load
Is there a way to optimize these kinds of queries?
SELECT
tickets.ticketID,
tickets.ticket,
tickets.name1,
tickets.address1,
tickets.city,
tickets.cstate,
tickets.zip,
tickets.caller_type,
tickets.phone,
tickets.caller,
tickets.caller_phone,
tickets.contact,
tickets.contact_phone,
tickets.call_back,
tickets.location,
tickets.printable_text,
tblnotes.ntDate,
tblnotes.ntText,
tblstatus.stDesc,
tblUsers.username
FROM tblusers
RIGHT OUTER JOIN tickets ON tblusers.ID = tickets.ownerID
LEFT OUTER JOIN tblstatus ON tblstatus.stID = tickets.statusID
LEFT OUTER JOIN tblnotes ON tblnotes.ntID = tickets.noteID
WHERE tblstatus.stDesc <> "Closed"

EDIT: try this
SELECT
tickets.ticketID,
tickets.ticket,
tickets.name1,
tickets.address1,
tickets.city,
tickets.cstate,
tickets.zip,
tickets.caller_type,
tickets.phone,
tickets.caller,
tickets.caller_phone,
tickets.contact,
tickets.contact_phone,
tickets.call_back,
tickets.location,
tickets.printable_text,
tblnotes.ntDate,
tblnotes.ntText,
tblstatus.stDesc,
tblUsers.username
FROM tickets
INNER JOIN tblusers ON tblusers.ID = tickets.ownerID
INNER JOIN tblstatus ON tblstatus.stID = tickets.statusID
LEFT OUTER JOIN tblnotes ON tblnotes.ntID = tickets.noteID
WHERE tickets.statusID <> 3
posting as an answer, as I am unable to comment
You have a condition where tblstatus.stDesc <> "Closed"
assuming you have an index here on stID
change that to where tblstatus.stID <> put the id value
also change your left outer joins to inner joins, as any ways you have a where condition, you can keep the left join on tblnotes as I am not sure if it may have a row corresponding to tbltickets
i will also move the tickets table to from and then do an inner join with tblusers
use left outer join only when the join table may not have data, but you still want to show data from your main table

Related

PHP MySQL: Join 3 tables but

I have 3 tables, errorcode_table, description_table, and customer_table.
The query below will display all records that are in the errorcode_table and I have an inner join that will also display the customer_table as per the serial number in both tables.
SELECT
errorcode_table.error,
errorcode_table.deviceserialnumber,
customer_table.serialnumber,
customer_table.customer,
FROM errorcode_table
INNER JOIN customer_table
ON errorcode_alert_table.deviceserialnumber = customerinfo_table.serialnumber
Now I want to also display the description of the error code as well, here's my attempt:
SELECT
errorcode_table.error,
errorcode_table.serialnumber,
customer_table.serialnumber,
customer_table.customer,
description.serialnumber
description.info
FROM errorcode_table
INNER JOIN customer_table
RIGHT JOIN description_table
ON errorcode_table.deviceserialnumber = customer_table.serialnumber
ON errorcode_table.deviceserialnumber = description_table.serialnumber
Now I'm not getting any records. Please assist.
The ON clause for each join should appear immediately after each join condition. And you can introduce table aliases to make the query easier to read.
SELECT
e.error,
e.serialnumber,
c.serialnumber,
c.customer,
d.serialnumber,
d.info
FROM errorcode_table e
INNER JOIN customer_table c
ON e.deviceserialnumber = c.serialnumber
RIGHT JOIN description_table d
ON e.deviceserialnumber = d.serialnumber;

SQL Query Left Join Tables

I was sure to implement yesterday and Have used LEFT JOIN if the other table has no value.
My Problem now is What if you are unsure which table has value and which table has value.
I have tried this query.
$query ="SELECT record.student_name,record.student_id,record.student_finger,record.student_section,record.activity_type,record.activity_title,record.score,record.teacher_id,record.activity_id,record.subject_id,attendance.status,attendance.date
FROM tbl_record record
LEFT JOIN tbl_attendance attendance on record.student_id=attendance.student_number
WHERE record.subject_id='$subject_id' and record.teacher_id='$teacher_id' and record.student_section='$section';";
But Unfortunately, If my record table is empty, It will not show anything.
What Im tryng to achieve is,
If table_record is empty and tbl_attendance is not, it will show records in tbl_attendance,
and if table_attendance is empty and table_record is not, it will show records in table_record.
Change LEFT JOIN to FULL OUTER JOIN, adapt the WHERE clause and let us know how it goes.
SELECT
record.student_name,
coalesce(record.student_id, attendance.student_number),
record.student_finger,
record.student_section,
record.activity_type,
record.activity_title,
record.score,
record.teacher_id,
record.activity_id,
record.subject_id,
attendance.status,
attendance.date
FROM tbl_record record
FULL OUTER JOIN tbl_attendance attendance on record.student_id=attendance.student_number
WHERE (record.subject_id='$subject_id' and record.teacher_id='$teacher_id'
and record.student_section='$section')
or record.subject_id is null;
This is a draft MySql version, where FULL OUTER JOIN is not supported. You can replace all record.* fields with NULLs in the RIGHT JOIN part:
SELECT
record.student_name,
record.student_id,
record.student_finger,
record.student_section,
record.activity_type,
record.activity_title,
record.score,
record.teacher_id,
record.activity_id,
record.subject_id,
attendance.status,
attendance.date
FROM tbl_record record
LEFT JOIN tbl_attendance as attendance on
record.student_id = attendance.student_number
WHERE (record.subject_id='$subject_id' and record.teacher_id='$teacher_id'
and record.student_section='$section')
UNION
SELECT
record.student_name,
attendance.student_number,
record.student_finger,
record.student_section,
record.activity_type,
record.activity_title,
record.score,
record.teacher_id,
record.activity_id,
record.subject_id,
attendance.status,
attendance.date
FROM tbl_record as record
RIGHT JOIN tbl_attendance as attendance on
record.student_id = attendance.student_number
WHERE record.subject_id is null
;
Just Change "Left JOIN" to "FULL OUTER JOIN"
SELECT *
FROM tbl_Students S
FULL OUTER JOIN tbl_Attendance A
ON S.StudentID = A.AttendanceStudentID

How to make LEFT OUTER JOIN except some colums?

I have 3 tables:
First "placement"
Second "user_info"
Third "user_placements"
I want to get all placement data with user infos,
How to do it?
I tried this, but result it not what I expected:
SELECT *, user_placements.id AS user_placements_id, placement.id AS placement_id
FROM placement
LEFT OUTER JOIN user_placements ON placement.id = user_placements.id_placement
you need to one more join with user info
SELECT placement.*,user_info.id as user_info_id,user_info.name as user_name,user_info.mobile as user_mobile
FROM placement LEFT OUTER JOIN user_placements ON placement.id = user_placements.id_placement
LEFT OUTER JOIN user_info ON user_info.id = user_placements.id_user
You are missing the second join:
SELECT *
FROM placement AS p
JOIN user_placements AS up ON p.id = up.id_placement
JOIN user_info AS u ON up.id_user = u.id
Replace the wildcard with the data you want.
You will of course get duplicated data with this query.

Inner Join only returning values if match is in all four tables

I have the following INNER JOIN statement and It is only returning results if all four tables have a match for the order number in them.
I need it to include every result in the main table KC_Orders regardless of the equivalent contents of each INNER JOIN tables in the $sql
I understand that this is the point of the INNER JOIN but I need it do something else.
$sql = "SELECT *
FROM `KC_Orders`
INNER JOIN `KC_Payments`
ON KC_Orders.orderNumber = KC_Payments.orderNumber
INNER JOIN `KC_OrderStatus`
ON KC_Orders.orderNumber = KC_OrderStatus.orderNumber
INNER JOIN `KC_Statuses`
ON KC_OrderStatus.statusID = KC_Statuses.statusID";
$AllOrders = $db->query($sql);
Use left outer joins
SELECT *
FROM
`KC_Orders`
LEFT JOIN `KC_Payments`
ON KC_Orders.orderNumber = KC_Payments.orderNumber
LEFT JOIN `KC_OrderStatus`
ON KC_Orders.orderNumber = KC_OrderStatus.orderNumber
LEFT JOIN `KC_Statuses`
ON KC_OrderStatus.statusID = KC_Statuses.statusID
If there is always a status available, you can keep the inner join for the KC_Statuses table
SELECT *
FROM
A
LEFT JOIN B
ON A.id = B.id
... means that all the records from A will be returned and only the records from B that match a record from A. Records from A are returned even when there is no matching record in B.
It sounds like you want an OUTER JOIN rather than an INNER JOIN.
If you want all rows from the KC_Orders table, then put that table first in the FROM clause, and use a LEFT JOIN on the other tables. (The OUTER keyword is not required.) This will return all rows from the KC_Orders table, even if no matching row is found in the other tables. NULL values will be returned in place of value from "missing" rows.
SELECT *
FROM `KC_Orders`
LEFT
JOIN `KC_Payments`
ON KC_Orders.orderNumber = KC_Payments.orderNumber
LEFT
JOIN `KC_OrderStatus`
ON KC_Orders.orderNumber = KC_OrderStatus.orderNumber
LEFT
JOIN `KC_Statuses`
ON KC_OrderStatus.statusID = KC_Statuses.statusID

Mysql Query Left Join Condition Problem

I have a litte problem with a mysql query.
I use 5 tables:
user_has_data (uid, dataid); users (uid, uname); user_in_group(uid, groupid, data); groups(groupid, data, packageid); packages(packageid, name)
all ids are PK. I want to build a sql query that finds a user, which belongs to a specified dataid, by its uname and checks if the user is in a group (relation in table user_in_group) belonging to a specified package (a group is assigned to one package). if so data from users, package and group should be fetched, otherwise only the user data should be fetched. Therefore I use left joins, so I can also get the users with no group:
SELECT `uac`.`uid`, `u`.`uid`, `uig`.`groupid`, `ag`.`packageid`
FROM `user_has_data` AS `uac`
INNER JOIN `users` AS `u` ON u.uid = uac.uid
LEFT JOIN `user_in_group` AS `uig` ON uig.uid = uac.uid
LEFT JOIN `groups` AS `ag` ON (ag.groupid = uig.groupid) AND (ag.packageid = 2)
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
GROUP BY `u`.`uid`
Unfortunately I get wrong results: I get groups that have a different packageid than stated in the join, if the user has another group assigned to him with a different packageid.
probably this is because the first left join has no restrictions to packageid and the second is a left join and so it has no restrictions on the result (packageid is NULL for all results, but should have values). If I change the second left join to a ordinary join, the group problem would be fixed but the query cant find users without group any more.
Any ideas how to fix this or even possible?
thanks in advance!
Are you saying that you are actually seeing the value ag.packageid = 2 in your query results?
If not, I think you might try something like:
SELECT `uac`.`uid`, `u`.`uid`, `g`.`groupid`, `g`.`packageid`
FROM `user_has_data` AS `uac`
INNER JOIN `users` AS `u` ON u.uid = uac.uid
LEFT JOIN (`user_in_group` AS `uig`
INNER JOIN `groups` AS `ag` ON (ag.groupid = uig.groupid) AND (ag.packageid = 2) )
AS `g` ON uac.uid = g.uid
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
GROUP BY `u`.`uid`
Because you are limiting your search to a specific group packageid of '2', why not just make both of your LEFT JOIN INNER JOINS and then throw in ag.packageid = 2 in your WHERE clause?
SELECT `uac`.`uid`, `u`.`uid`, `uig`.`groupid`, `ag`.`packageid`
FROM `user_has_data` AS `uac`
INNER JOIN `users` AS `u` ON u.uid = uac.uid
LEFT OUTER JOIN `user_in_group` AS `uig` ON uig.uid = uac.uid
LEFT OUTER JOIN `groups` AS `ag` ON ag.groupid = uig.groupid
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
AND (ag.packageid = 2 OR uig.uid IS NULL)
GROUP BY `u`.`uid`
I know LEFT JOIN and LEFT OUTER JOIN mean the same thing, but I like to be explicit. With the condition in your join, I bet you were getting groups with different packages, but weren't getting the packages?