MySQL query result fluctuating - php

My problem is more clear on this post: Select all categories with latest post, user, and topic information
——————————————————————————————————————————
I have a query that pulls a list of the categories for my forum along with the latest post in that category. The results come back as expected, except that sub_post information being pulled in the LEFT JOIN fp1 changes if if run the query several times.
I first noticed this problem when viewing my webpage and refreshing several times. The post that it is pulling fluctuates between 3 posts. I'm not sure how this is even possible, unless there is something wrong with the query.
Please, take a look at my query below and let me know if there is something I am doing wrong that might explain this odd behavior.
Cheers.
SELECT fc1.id AS cat_id, fc1.cat_name AS cat_name,
fc1.cat_description AS cat_description, fc1.cat_views as cat_views, fp1.*
FROM forum_categories as fc1
LEFT JOIN (SELECT fp2.id AS sub_post_id,
fp2.post_date as sub_post_date,
fp2.post_topic as sub_post_topic,
u2.id as sub_user_id, u2.username as sub_username,
ft2.topic_subject as sub_topic_subject, ft2.topic_cat as sub_topic_cat
FROM forum_posts as fp2
LEFT JOIN users as u2 on fp2.post_by = u2.id
LEFT JOIN forum_topics as ft2 on ft2.id = fp2.post_topic
LEFT JOIN forum_categories as fcats on fcats.id = ft2.topic_cat
ORDER BY fp2.id DESC)
as fp1 on fp1.sub_topic_cat = fc1.id
GROUP BY fc1.id;
EXPLAIN SELECT:
+----+-------------+------------+--------+-------------------------+-------------+---------+--------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+-------------------------+-------------+---------+--------------------+------+-------------+
| 1 | PRIMARY | fc1 | index | PRIMARY,cat_name_unique | PRIMARY | 8 | NULL | 3 | Using where |
| 1 | PRIMARY | <derived2> | ref | <auto_key0> | <auto_key0> | 9 | tpw.fc1.id | 9 | NULL |
| 2 | DERIVED | fp2 | index | NULL | PRIMARY | 8 | NULL | 92 | NULL |
| 2 | DERIVED | u2 | eq_ref | PRIMARY | PRIMARY | 8 | tpw.fp2.post_by | 1 | NULL |
| 2 | DERIVED | ft2 | eq_ref | PRIMARY | PRIMARY | 8 | tpw.fp2.post_topic | 1 | NULL |
| 2 | DERIVED | fcats | eq_ref | PRIMARY | PRIMARY | 8 | tpw.ft2.topic_cat | 1 | Using index |
+----+-------------+------------+--------+-------------------------+-------------+---------+--------------------+------+-------------+
I have 3 tables: forums_categories, forums_topics, and forums_posts. I am trying to list the categories along with the latest post in that category. The forums_post is linked to forums_topics by a post_topic and the forums_topics is linked to the forums_categories with a topic_cat.

This was solved by _pala on this other question: https://stackoverflow.com/a/30048334/4864675
I was going about the query wrong which accounted for the odd behavior. Thanks _pala!
Here's the SQL that worked it out for me provided by user _pala:
select fc.cat_name, fc.cat_description, fc.cat_views, u.username, fp.post_date, ft.topic_subject
from forum_categories fc
inner join forum_topics ft
on fc.id = ft.topic_cat
inner join forum_posts fp
on fp.post_topic = ft.id
inner join users u
on fp.post_by = u.id
inner join (
select topic_cat, max(fp.id) most_recent_post
from forum_topics ft
inner join forum_posts fp
on fp.post_topic = ft.id
group by topic_cat
) q
on q.topic_cat = ft.topic_cat
and fp.id = q.most_recent_post;

LEFT JOIN forum_categories as fcats on fcats.id = ft2.topic_cat
I believe the inclusion of that LEFT JOIN has no impact on the result other than to slow down processing. Remove it.
ORDER BY fp2.id DESC
That ORDER BY has no impact on the result because the GROUP BY will not care. Remove it.
If neither of those helps, then explain this:
The post that it is pulling fluctuates between 3 posts.
And please provide EXPLAIN SELECT ...

Related

This Mysql SQL Select query takes 33 mins to execute

Title says it all. Do you think anyone could help me untangle this? or if someone could point me out to what else could be causing it to take so much time. The query takes about half an hour to run. The guy who wrote this tried doing it in a loop, by removing the table from the last join statement and then querying the field.title for each vote. i was hoping to bring the result to about 5 mins.
some extra info:
The query result is 83,531 rows
The vote table size is 30 MB (261,169 rows)
SELECT `vote`.`id` `vote_id`, `branch`.`name` `branch`, `brand`.`name` `brand`, DATE(vote.created_at) `date`, HOUR(vote.created_at) `time_hour`,
MINUTE(vote.created_at) `time_minute`, `vote`.`is_like`, `voter`.`name`, `voter`.`telephone`, `voter`.`email`, popups_votes.title `popup_title`,
popups_votes.value `popup_value`, GROUP_CONCAT(dis.field SEPARATOR '|') `reasons`
FROM (`vote`)
LEFT JOIN `voter` ON `voter`.`id` = `vote`.`voter_id`
LEFT JOIN `device` ON `device`.`id` = `vote`.`device_id`
LEFT JOIN `branch` ON `branch`.`id` = `device`.`branch_id`
LEFT JOIN `brand` ON `brand`.`id` = `branch`.`brand_id`
LEFT JOIN `popups_votes` ON popups_votes.vote_id = vote.id
LEFT JOIN (SELECT vote_dislike.vote_id `vote_id`, field.title `field` FROM vote_dislike
LEFT JOIN branch_dislike_field ON branch_dislike_field.id = vote_dislike.branch_dislike_id
LEFT JOIN field ON field.id = branch_dislike_field.field_id) dis
ON dis.vote_id = vote.id
WHERE (vote.device_id in
(
Select d.id
From device d
WHERE d.branch_id IN (SELECT id FROM branch WHERE brand_id = 7)
)
)
AND (vote.created_at >= FROM_UNIXTIME('$from_time') AND vote.created_at <= FROM_UNIXTIME('$to_time') )
GROUP BY vote.id
EDIT: this is the explain {query} output:
+------+-------------+----------------------+--------+----------------------+-----------+---------+-------------------------------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------------------+--------+----------------------+-----------+---------+-------------------------------------------+------+----------------------------------------------+
| 1 | PRIMARY | branch | ref | PRIMARY,brand_id | brand_id | 4 | const | 20 | Using index; Using temporary; Using filesort |
| 1 | PRIMARY | d | ref | PRIMARY,branch_id | branch_id | 4 | river_back.branch.id | 1 | Using index |
| 1 | PRIMARY | vote | ref | device_id,created_at | device_id | 4 | river_back.d.id | 1200 | Using where |
| 1 | PRIMARY | voter | eq_ref | PRIMARY | PRIMARY | 4 | river_back.vote.voter_id | 1 | |
| 1 | PRIMARY | device | eq_ref | PRIMARY | PRIMARY | 4 | river_back.d.id | 1 | |
| 1 | PRIMARY | branch | eq_ref | PRIMARY | PRIMARY | 4 | river_back.device.branch_id | 1 | Using where |
| 1 | PRIMARY | brand | eq_ref | PRIMARY | PRIMARY | 4 | river_back.branch.brand_id | 1 | Using where |
| 1 | PRIMARY | popups_votes | ref | vote_id | vote_id | 5 | river_back.vote.id | 602 | |
| 1 | PRIMARY | vote_dislike | ref | vote_id | vote_id | 4 | river_back.vote.id | 1 | |
| 1 | PRIMARY | branch_dislike_field | eq_ref | PRIMARY | PRIMARY | 4 | river_back.vote_dislike.branch_dislike_id | 1 | Using where |
| 1 | PRIMARY | field | eq_ref | PRIMARY | PRIMARY | 4 | river_back.branch_dislike_field.field_id | 1 | Using where |
+------+-------------+----------------------+--------+----------------------+-----------+---------+-------------------------------------------+------+----------------------------------------------+
You should check that all the data you are selecting are indexed and you have foreign keys.
How do MySQL indexes work?
Basically an index on a table works like an index in a book (that's
where the name came from):
Let's say you have a book about databases and you want to find some
information about, say, storage. Without an index (assuming no other
aid, such as a table of contents) you'd have to go through the pages
one by one, until you found the topic (that's a full table scan). On
the other hand, an index has a list of keywords, so you'd consult the
index and see that storage is mentioned on pages 113-120,231 and 354.
Then you could flip to those pages directly, without searching (that's
a search with an index, somewhat faster).
Basics of Foreign Keys in MySQL?
FOREIGN KEYS just ensure your data are consistent.
They do not improve queries in sense of efficiency, they just make
some wrong queries fail.
Do not use LEFT unless you are expecting the "right" table to have missing rows.
In particular, the Optimizer probably cannot start with the 'derived table' since it is hiding to the right of a LEFT.
Do not use IN ( SELECT ... ); if possible change to EXISTS ( SELECT * ...) or JOIN.
Try to avoid the "inflate-deflate" caused by JOIN ... GROUP BY. If possible find the ids of interest without needing a GROUP BY, then JOIN to the other tables.
Putting many of those together, does this get you close to the desired result, at least in the sense of getting the correct vote.id values?
SELECT vote.id
FROM vote AS v
JOIN (
SELECT vote_dislike.vote_id `vote_id`, field.title `field`
FROM vote_dislike AS vd
LEFT JOIN branch_dislike_field AS bd
ON bd.id = vd.branch_dislike_id
LEFT JOIN field
ON field.id = bd.field_id
) AS dis ON dis.vote_id = v.id
JOIN device AS d ON v.device_id = d.id
JOIN branch AS b ON d.branch_id = b.id
WHERE b.brand_id = 7
AND v.created_at >= ...
AND v.created_at <= ...
Then:
SELECT lots of stuff
FROM ( the above query ) AS x
JOIN vote v ON x.id = v.id -- yes, dig back into `vote` for the other stuff
JOIN voter ...
JOIN ...
but with no GROUP BY.

MySQL - inner join - add column with value based on other value

I'm struggling with mysql joins :/
I've multiple tables inside database fe. tasks, users etc.
Table tasks containing tasks with various variables, but the most important - id's of users signed to task (as different roles inside the task - author, graphic, corrector):
+---------+-------------+--------------+
| task_id | task_author | task_graphic |
+---------+-------------+--------------+
| 444 | 1 | 2 |
+---------+-------------+--------------+
Table users
+---------+----------------+------------+-----------+
| user_id | user_nice_name | user_login | user_role |
+---------+----------------+------------+-----------+
| 1 | Nice Name #1 | login1 | 0 |
+---------+----------------+------------+-----------+
| 2 | Bad Name #2 | login2 | 1 |
+---------+----------------+------------+-----------+
Using PDO I'm getting the whole data I want while using INNER JOIN with data from different tables (and $_GET variable)
SELECT tasks.*, types.types_name, warehouse.warehouse_id, warehouse.warehouse_code, warehouse.warehouse_description
FROM tasks
INNER JOIN types ON types.types_id = tasks.task_id
INNER JOIN warehouse ON warehouse.warehouse_id = tasks.task_id
WHERE tasks.task_id = '".$get_id."'
ORDER BY tasks.task_id
Above query returns:
+---------+--------------+--------------+----------------+------------+-----------+------------------+------------------------+------------+-------------+-----------------+-----------+----------------+--------------------+---------------------+-----------+---------------------+------------------+---------------------+
| task_id | task_creator | task_graphic | task_purchaser | task_title | task_lang | task_description | task_description_files | task_files | task_status | task_prod_index | task_type | task_print_run | task_print_company | task_warehouse_code | task_cost | task_time_added | task_deadline | task_date_warehouse |
+---------+--------------+--------------+----------------+------------+-----------+------------------+------------------------+------------+-------------+-----------------+-----------+----------------+--------------------+---------------------+-----------+---------------------+------------------+---------------------+
| 2 | 1 | 2 | 1 | Test | PL | Lorem ipsum (?) | | | w | 2222 | 3 | 456546 | Firma XYZ | 2 | 124 | 29.09.2016 15:48:20 | 01.10.2016 12:00 | 07.10.2016 14:00 |
+---------+--------------+--------------+----------------+------------+-----------+------------------+------------------------+------------+-------------+-----------------+-----------+----------------+--------------------+---------------------+-----------+---------------------+------------------+---------------------+
And I'd like to get query with added user_nice_name after task_creator, task_author and task_graphic - obviously nice names selected from table users based on ID's provide in 3 above fields fe.
+---------+--------------+------------------------------------+--------------+--------------------------------------+
| task_id | task_creator | task_creator_nn | task_graphic | task_graphic |
+---------+--------------+------------------------------------+--------------+--------------------------------------+
| 2 | 1 | Nice Name (from task_creator ID=1) | 2 | Nice Name (from task_graphic ID = 2) |
+---------+--------------+------------------------------------+--------------+--------------------------------------+
How can I achieve that?
You need three joins:
SELECT t.*,
uc.user_nice_name as creator_name,
ug.user_nice_name as graphic_name,
up.user_nice_name as purchaser_name,
ty.types_name, w.warehouse_id, w.warehouse_code, w.warehouse_description
FROM tasks t INNER JOIN
types ty
ON ty.types_id = t.task_id INNER JOIN
warehouse w
ON w.warehouse_id = t.task_id LEFT JOIN
users uc
ON uc.user_id = t.task_creator LEFT JOIN
users ug
ON ug.user_id = t.task_graphic LEFT JOIN
users up
ON up.user_id = t.task_purchaser
WHERE t.task_id = '".$get_id."'
ORDER BY t.task_id;
Notes:
Table aliases make the query easier to write and to read. They are also required because you have three references to users in the FROM clause.
This uses LEFT JOIN for the users in case some of the reference values are missing.
You need to work on your naming. It doesn't make sense that a "warehouse" id matches a "task" id. Or that a "task" id matches a "types" id. But that is how you phrased the query in your question.
The ORDER BY effectively does nothing, because all rows have the same task_id.
Assuming that the task_graphic_name is inside a table name task_graphic_table and the relation field are task_graphic_id
SELECT tasks.*
, types.types_name
, warehouse.warehouse_id
, warehouse.warehouse_code
, warehouse.warehouse_description
, users.user_nice_name
FROM tasks
INNER JOIN types ON types.types_id = tasks.task_id
INNER JOIN warehouse ON warehouse.warehouse_id = tasks.task_id
INNER JOIN users ON users.user_nice_name = tasks.task_graphic
WHERE tasks.task_id = '".$get_id."'
ORDER BY tasks.task_id
And if you need the column appear in a specific order you should explicitally call the column name in sequence eg:
SELECT tasks.col1
, task.col2
, types.types_name
, warehouse.warehouse_id
, warehouse.warehouse_code
, task.col2
, warehouse.warehouse_description
, task_graphic_table.task_graphic_name
Add two sub query in with your query. like
SELECT tasks.*,
....
....,
(select user_nice_name from users where id = tasks.task_author) AS task_creator_name,
(select user_nice_name from users where id = tasks.task_graphic) AS task_graphic_name
FROM tasks
INNER JOIN types ON types.types_id = tasks.task_id
....
....

PHP MySQL joining two tables with conditional joins

So, I have a database that I am creating. It stores information about families and each family member. It then uses those records to associate invoices to either a family or family member.
My dilemma is that I need to list all of these invoices to a page under the families record i.e. create a list of invoices associated to either the family itself or an individual family member.
Table Structure
invoices
id | date_entered | invoice_date | invoice_number | invoice_amount | client_type | unique_id | supplier_type | supplier_id | category_id | childcare_hours
---+--------------+--------------+----------------+----------------+-------------+-----------+---------------+-------------+-------------+----------------
1 | 1411098397 | 1411048800 | 123 | 0.01 | 0 | 137 | 0 | 139 | 5 | NULL
families
id | ufi | last_name | address_1 | address_2 | city_id | phone | mobile | email | f_d_worker_1 | f_d_worker_2 | status_id | trans_date | entry_date | exit_date | eligible_date | active_date | lga_loc_id | facs_loc_id | ind_status_id | referral_id | active_status | comm_org_id | notes
---+----------+-----------------+-------------+-----------+---------+-------+--------+-------+--------------+--------------+-----------+------------+------------+-----------+---------------+-------------+------------+-------------+---------------+-------------+---------------+-------------+-------
1 | 1-XEWUDZ | Forsyth - Ennis | Skinner St. | NULL | NULL | NULL | NULL | NULL | 13 | NULL | 1 | NULL | 1341324000 | NULL | 1341842400 | 1342620000 | 7 | 1 | 3 | NULL | 1 | 1 | NULL
clients (family members)
id | upi | last_name | first_name | birthdate | sex | phone | mobile | email | indig_status_id | referral_id | relationship_id | preschool_id | family_id | notes
---+----------+-----------+------------+------------+-----+-------+--------+-------+-----------------+-------------+-----------------+--------------+-----------+------
1 | 1-XFCBBP | Ennis | Jason | 20/09/1996 | 1 | NULL | NULL | NULL | 3 | NULL | NULL | NULL | 1 | NULL
My current SQL looks like:
SELECT `invoices`.`id`, `invoices`.`date_entered`, `invoices`.`invoice_date`, `invoices`.`invoice_number`, `invoices`.`invoice_amount`, `invoices`.`client_type`, `invoices`.`unique_id`, `unique1`.`ufi`, `unique2`.`upi`, `unique1`.`last_name`, `invoices`.`supplier_type`, `invoices`.`supplier_id`, `suppliers`.`name`, `invoices`.`category_id`, `cat1`.`name`, `cat2`.`name`, `invoices`.`childcare_hours`
FROM `invoices`
LEFT OUTER JOIN `suppliers` ON `suppliers`.`id` = `invoices`.`supplier_id`
LEFT OUTER JOIN `categories` cat1 ON `cat1`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `preschool_types` cat2 ON `cat2`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `families` unique1 ON `unique1`.`id` = `invoices`.`unique_id`
LEFT OUTER JOIN `clients` unique2 ON `unique2`.`id` = `invoices`.`unique_id`
WHERE (`invoices`.`unique_id` = ? AND `unique1`.`ufi` = ?) LIMIT 0, 10
But what I need a query that checks the client_type column and if it equals 1 it needs to look in the clients table BUT it needs to look for members of the same family, identified by the id row in the families table
SOLUTION
Ok, so after much, much (much) screwing around and a little research. It appears that #cupid was correct (Although very brief in his answer).
And I will explain the solution better (in hope that this will help someone later).
The UNION option in MySQL (and most likely other SQL) allows you to combine the result sets of two (or more) SELECT queries, into one result set. This is extremely helpful if you have similar data, in separate tables that you may want to select easily and process as one request. Also helpful (in my case) for pagination, by allowing you to utilise SQL's LIMIT option.
One thing to take into consideration is that, the UNION syntax uses the columns from the first SELECT statement as the column names for all following queries, also you need to make sure that you have the same amount of columns selected in all queries for this to work.
(
SELECT
`invoices`.`id`,
`invoices`.`date_entered`,
`invoices`.`invoice_date`,
`invoices`.`invoice_number`,
`invoices`.`invoice_amount`,
`invoices`.`client_type`,
`invoices`.`unique_id`,
`clients`.`upi`,
`clients`.`last_name`,
`clients`.`family_id`,
`invoices`.`supplier_type`,
`invoices`.`supplier_id`,
`suppliers`.`name`,
`invoices`.`category_id`,
`cat1`.`name`,
`cat2`.`name`,
`invoices`.`childcare_hours`
FROM
(
`invoices`
LEFT OUTER JOIN `suppliers` ON `suppliers`.`id` = `invoices`.`supplier_id`
LEFT OUTER JOIN `categories` cat1 ON `cat1`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `preschool_types` cat2 ON `cat2`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `clients` ON `clients`.`id` = `invoices`.`unique_id`)
WHERE
`clients`.`family_id` = 47 AND `invoices`.`client_type` = 1
)
UNION
(
SELECT
`invoices`.`id`,
`invoices`.`date_entered`,
`invoices`.`invoice_date`,
`invoices`.`invoice_number`,
`invoices`.`invoice_amount`,
`invoices`.`client_type`,
`invoices`.`unique_id`,
`families`.`ufi`,
`families`.`last_name`,
`families`.`id`,
`invoices`.`supplier_type`,
`invoices`.`supplier_id`,
`suppliers`.`name`,
`invoices`.`category_id`,
`cat1`.`name`,
`cat2`.`name`,
`invoices`.`childcare_hours`
FROM `invoices`
LEFT OUTER JOIN `suppliers` ON `suppliers`.`id` = `invoices`.`supplier_id`
LEFT OUTER JOIN `categories` cat1 ON `cat1`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `preschool_types` cat2 ON `cat2`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `families` ON `families`.`id` = `invoices`.`unique_id`
WHERE
`invoices`.`unique_id` = 47 AND `invoices`.`client_type` = 0
)
Have you thought about using UNION?

Query with JOIN slow

why my query take about 2 minutes to process?
i need to take attribute from 8 table.
how can i join those table and make it a fast query?
the reason why i want to join those table is bacause i want to fetchAll(PDO::FETCH_ASSOC) from user input progCode
this is my query :
"SELECT DISTINCT a.`ProgCode`, a.`Program`
FROM (select `i`.`name` AS `LC`,`f`.`name` AS `Intake`,`a`.`student_id`
AS `student_id`,`b`.`matricNo`
AS `matricNo`,`b`.`name`
AS `Nama`,`a`.`sem_id`
AS `sem_id`,`c`.`name`
AS `Sessi`,`e`.`code`
AS `ProgCode`,`e`.`name`
AS `Program`,`a`.`sub_id`
AS `sub_id`,`d`.`code`
AS `SubCode`,`d`.`name`
AS `Subject`,`a`.`grade`
AS `grade`,`h`.`credit`
AS `CurrentCreditHour`,`g`.`totalcredit`
AS `TotalCreditHour`,`g`.`gpa`
AS `GPA`,`g`.`cgpa`
AS `CGPA` from ((((((((`admin_sub_mark` `a` join `enrl_student` `b`)
join `struc_session` `c`)
join `struc_session` `f`)
join `struc_subject` `d`)
join `struc_program` `e`)
join `admin_sem_wise_cgpa` `g`)
join `admin_sem_wise_gpa` `h`)
join `struc_learningcentre` `i`)
where ((`b`.`id` = `a`.`student_id`)
and (`d`.`id` = `a`.`sub_id`)
and (`c`.`id` = `a`.`sem_id`)
and (`e`.`id` = `b`.`program_id`)
and (`f`.`id` = `b`.`intake_id`)
and (`i`.`id` = `b`.`learningCenter_id`)
and (`a`.`student_id` = `g`.`student_id`)
and (`a`.`sem_id` = `g`.`sem_id`)
and (`h`.`student_id` = `g`.`student_id`)
and (`h`.`sem_id` = `g`.`sem_id`)) order by `b`.`name`) a
ORDER BY `Program` ASC"
this is my explain query:
id| select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
1 | SIMPLE | g | ALL | NULL |NULL | NULL | NULL| 6049 | Using temporary;
Using filesort
1 | SIMPLE | h | ALL | NULL | NULL | NULL | NULL | 6055 | Using where |
1 | SIMPLE | c | eq_ref | PRIMARY | PRIMARY | 257 | educate_aeu2.g.sem_id 1
1 | SIMPLE | b | eq_ref | PRIMARY | PRIMARY | 257 | educate_aeu2.h.student_id 1 Using where
1 | SIMPLE | f | eq_ref |PRIMARY | PRIMARY | 257 | educate_aeu2.b.intake_id 1
1 | SIMPLE | e | eq_ref | PRIMARY | PRIMARY | 257 | educate_aeu2.b.program_id 1
1 | SIMPLE | i | eq_ref | PRIMARY | PRIMARY | 257 | educate_aeu2.b.learningCenter_id 1
1 | SIMPLE | a |ALL | NULL | NULL | NULL | NULL | 17077 | Using where
1 | SIMPLE | d | eq_ref | PRIMARY | PRIMARY | 257 | educate_aeu2.a.sub_id 1
You are retreiving a lot of fields in the inner select and doing a sort, then ignoring most of those fields and doing another sort. This will waste time
Quick clean up of the code gives:-
SELECT DISTINCT
e.code AS ProgCode,
e.name AS Program
FROM admin_sub_mark a
JOIN enrl_student b ON b.id = a.student_id
JOIN struc_session c ON c.id = a.sem_id
JOIN struc_session f ON f.id = b.intake_id
JOIN struc_subject d ON d.id = a.sub_id
JOIN struc_program e ON e.id = b.program_id
JOIN admin_sem_wise_cgpa g ON a.student_id = g.student_id AND a.sem_id = g.sem_id
JOIN admin_sem_wise_gpa h ON h.student_id = g.student_id AND h.sem_id = g.sem_id
JOIN struc_learningcentre i ON i.id = b.learningCenter_id
ORDER BY e.name ASC
Not sure whether you need to access all the tables.
Further what indexes do you have on the tables? If a query like this is running slowly then the culprit is normally the indexes but without knowing what they are (or better, the output from an EXPLAIN) we will struggle to provide any useful help

How to SELECT records from One table If Matching Record In Not Found In Other Table

Halo i am trying for a query to select record from one table say 'deal_asking' only if a matching record is not found in the second table 'deal_unpluged'. this what i does (below) selecting record using LEFT JOIN and then filter the record in PHP side.
What i am looking for an Mysql query way of solution for this problem please help..
thanks in advance...
SELECT DA.das_id, DU.das_id_fk
FROM deal_asking DA
LEFT JOIN deal_unpluged DU ON DA.das_id= DU.das_id_fk
WHERE department='8'
ORDER BY das_id ASC LIMIT 10 OFFSET 0
Just add this to your WHERE clause:
AND DU.das_id_fk IS NULL
Say I have the following two tables:
+-------------------------+ +-------------------------+
| Person | | Pet |
+----------+--------------+ +-------------------------+
| PersonID | INT(11) | | PetID | INT(11) |
| Name | VARCHAR(255) | | PersonID | INT(11) |
+----------+--------------+ | Name | VARCHAR(255) |
+----------+--------------+
And my tables contain the following data:
+------------------------+ +---------------------------+
| Person | | Pet |
+----------+-------------+ +-------+----------+--------+
| PersonID | Name | | PetID | PersonID | Name |
+----------+-------------+ +-------+----------+--------+
| 1 | Sean | | 5 | 1 | Lucy |
| 2 | Javier | | 6 | 1 | Cooper |
| 3 | tradebel123 | | 7 | 2 | Fluffy |
+----------+-------------+ +-------+----------+--------+
Now, if I want a list of all Persons:
SELECT pr.PersonID, pr.Name
FROM
Person pr
If I want a list of Persons that have pets (including their pet's names):
SELECT pr.PersonID, pr.Name, pt.Name AS PetName
FROM
Person pr
INNER JOIN Pet pt ON pr.PersonID = pt.PersonID
If I want a list of Persons that have no pets:
SELECT pr.PersonID, pr.`Name`
FROM
Person pr
LEFT JOIN Pet pt ON pr.PersonID = pt.PersonID
WHERE
pt.`PetID` IS NULL
If I want a list of all Persons and their pets (even if they don't have pets):
SELECT
pr.PersonID,
pr.Name,
COALESCE(pt.Name, '<No Pet>') AS PetName
FROM
Person pr
LEFT JOIN Pet pt ON pr.PersonID = pt.PersonID
If I want a list of Persons and a count of how many pets they have:
SELECT pr.PersonID, pr.Name, COUNT(pt.PetID) AS NumPets
FROM
Person pr
LEFT JOIN Pet pt ON pr.PersonID = pt.PersonID
GROUP BY
pr.PersonID, pr.Name
Same as above, but don't show Persons with 0 pets:
SELECT pr.PersonID, pr.Name, COUNT(pt.PetID) AS NumPets
FROM
Person pr
LEFT JOIN Pet pt ON pr.PersonID = pt.PersonID
GROUP BY
pr.PersonID, pr.Name
HAVING COUNT(pt.PetID) > 0

Categories