MySQL doesn't yet support Limit&& in/all? - mysql

my query is as follow:
SELECT * FROM `C_Institute`
WHERE `ID` IN
(SELECT `instituteID` FROM `C_Faculty` WHERE `ID`
IN (SELECT `facultyID` FROM `C_EducationalGroup` WHERE `ID`
IN (SELECT `educationalGroupID` FROM `C_StudyField` WHERE `ID`
IN (SELECT `studyFieldID` FROM `b_PersonEmployment` WHERE `personID`=1 ORDER BY `startDate` limit 1) )));
but mysql not support limit and in on subquery. I don't know how I can write this query.
can anyone help me please?
thanks in advance

You may rewrite this query a series of joins:
SELECT c1.*
FROM C_Institute c1
INNER JOIN C_Faculty c2
ON c1.ID = c2.instituteID
INNER JOIN C_EducationalGroup c3
ON c2.ID = c3.facultyID
INNER JOIN C_StudyField c4
ON c3.ID = c4.educationalGroupID
INNER JOIN b_PersonEmployment b
ON c4.ID = b.studyFieldID
WHERE b.personID = 1
ORDER BY b.startDate
LIMIT 1;

Assuming ID in each table is referring to the other table then,
Try this and let me know :
select * from C_Institute c join C_Faculty f on c.ID=F.instituteID left join C_EducationalGroup e on f.ID=e.facultyID left join C_StudyField sf on e.ID=sf.educationalGroupID left join b_PersonEmployment p on sf.ID=p.studyFieldID where p.personID=1 order by p.startDate limit 1;
Also, share your tables description for more clues

thanks for all your answer. but I think join is not good way to solve this problem. I've done it by two query(maybe not good idea but better than join):
SET #studyFieldID =(SELECT `studyFieldID` FROM `b_PersonEmployment` WHERE `personID`=1 ORDER BY `startDate` limit 1);
SELECT * FROM `C_Institute`
WHERE `ID` IN
(SELECT `instituteID` FROM `C_Faculty` WHERE `ID`
IN (SELECT `facultyID` FROM `C_EducationalGroup` WHERE `ID`
IN (SELECT `educationalGroupID` FROM `C_StudyField` WHERE `ID`=#studyFieldID
)));

Related

Replacing sub query with join in mysql

I have a mysql query like...
SELECT OrderTransaction.buyer, OrderTransaction.parent_id
FROM order_transactions as OrderTransaction
INNER JOIN (
SELECT buyer
FROM order_transactions as dy
left join orders as ebay on ebay.id=dy.parent_id
where ebay.status='0' and dy.parent_id IN (
SELECT parent_id
FROM order_shipping_details as ds
left join orders as ebays on ebays.id=ds.parent_id
where ebays.status='0' and ebays.combined=0
GROUP BY ds.Street
HAVING count(ds.id) > 1
) and ebay.combined=0
group by dy.buyer
) dup ON dup.buyer=OrderTransaction.buyer
left join orders as ebay on ebay.id=OrderTransaction.parent_id
where ebay.market_type!='shopclue' and ebay.status='0' and ebay.combined=0
I need to optimize this query and want to remove the inner select with joins.
Any help would be appreciated. Thanks in advance.
Try this code below might be running faster than the one u currently using:
DROP TEMPORARY TABLE IF EXISTS temp1;
CREATE TEMPORARY TABLE temp1;
SELECT buyer
FROM order_transactions AS dy
LEFT JOIN orders AS ebay ON ebay.id=dy.parent_id
WHERE ebay.status='0'
AND dy.parent_id
IN (
SELECT parent_id
FROM order_shipping_details AS ds
left join orders AS ebays ON ebays.id=ds.parent_id
where ebays.status='0' and ebays.combined=0
GROUP BY ds.Street
HAVING count(ds.id) > 1)
AND ebay.combined= '0'
;
SELECT
OrderTransaction.buyer,
OrderTransaction.parent_id
FROM order_transactions AS OrderTransaction
INNER JOIN temp1 AS tmp ON tmp.buyer = OrderTransaction.buyer
LEFT JOIN orders AS ebay ON ebay.id = OrderTransaction.parent_id
WHERE ebay.market_type! = 'shopclub' AND ebay.status = '0' and ebay.combined = '0'
Please let me know if you have any questions!

MySQL Query, (access mainquery from subquery)

I have a problem that I need a WHERE clause in a subquery that depends on the results of the main Query, otherwise my results would be wrong and the query takes too long / is not executeable.
The circumstances that I need this query to create a view which I need for a search server support the problem that I cannot split this into two queries, nor process it with a script dynamically.
The problem occurs with the following query:
SELECT `s`.`id` AS `seminar_id`, (SUM( `sub`.`seminar_rate` ) / COUNT( `sub`.`seminar_id` )) AS `total_rate`
FROM
(
SELECT (SUM( value ) / COUNT( * )) AS `seminar_rate` , `r`.`seminar_id`
FROM `rating` r
INNER JOIN `rating_item` ri ON `r`.`id` = `ri`.`rating_id`
WHERE `r`.`seminar_id` = `s`.`id`/* <- Here is my problem, this is inacessible */
GROUP BY `r`.`seminar_id`
) AS sub,
`seminar` s
INNER JOIN `date` d
ON `s`.`id` = `d`.`seminar_id`
INNER JOIN `date_unit` du
ON `d`.`id` = `du`.`date_id`
LEFT JOIN `seminar_subject` su
ON `s`.`id` = `su`.`seminar_id`
LEFT JOIN `subject` suj
ON `su`.`subject_id` = `suj`.`id`
INNER JOIN `user` u
ON `s`.`user_id` = `u`.`id`
INNER JOIN `company` c
ON `u`.`company_id` = `c`.`id`
GROUP BY `du`.`date_id`, `sub`.`seminar_id`
This query should calculate a total rate out of ratings for each Seminar.
However my ratings are stored in my "rating" table and should be processed live.
(Sidenote: If you wonder about all the joins: This query has alooot more SELECT'ed fields, I just removed them because they are not nesessary to solve the problem and to make the query look less complicated [I know it still is >.>]...)
The reason is that I want this results to be sortable by my search engine later depending
on the users sort parameters, thatswhy I need it inside this query.
The problem itself is pretty obvious:
ERROR 1054 (42S22): Unknown column 's.id' in 'where clause'
The subselect doesnt know about the results of the main query, is there a solution to bypass this?
Could someone give me a hint to get this working?
Thanks in advance.
Using your subquery in the JOIN you can eliminate the WHERE clause and achieve nearly the same result. Here is your modified query. Hope this solves your problem.
SELECT `s`.`id` AS `seminar_id`, (SUM( `sub`.`seminar_rate` ) / COUNT( `sub`.`seminar_id` )) AS `total_rate`
FROM `seminar` s
INNER JOIN
(
SELECT (SUM( value ) / COUNT( * )) AS `seminar_rate` , `r`.`seminar_id`
FROM `rating` r
INNER JOIN `rating_item` ri ON `r`.`id` = `ri`.`rating_id`
/*WHERE `r`.`seminar_id` = `s`.`id` <- Here is my problem, this is inacessible */
GROUP BY `r`.`seminar_id`
) AS sub ON s.id = sub.`seminar_id`
INNER JOIN `date` d
ON `s`.`id` = `d`.`seminar_id`
INNER JOIN `date_unit` du
ON `d`.`id` = `du`.`date_id`
LEFT JOIN `seminar_subject` su
ON `s`.`id` = `su`.`seminar_id`
LEFT JOIN `subject` suj
ON `su`.`subject_id` = `suj`.`id`
INNER JOIN `user` u
ON `s`.`user_id` = `u`.`id`
INNER JOIN `company` c
ON `u`.`company_id` = `c`.`id`
GROUP BY `du`.`date_id`, `sub`.`seminar_id`

Counting rows from a big mysql query (zend)

I a developing in zend and have a rather large mysql query. The query works fine and i get the list I expect. I am doing this using Select->Where.... below is the query.
SELECT DISTINCT `d`.* FROM `deliverable` AS `d` INNER JOIN `groups` AS `g1` ON d.id = g1.deliverable_id INNER JOIN `groupmembers` AS `gm1` ON g1.id = gm1.group_id LEFT JOIN `connection` AS `c` ON d.id = c.downstreamnode_id LEFT JOIN `deliverable` AS `d1` ON c.upstreamnode_id = d1.id INNER JOIN `deliverable` AS `d2` ON CASE WHEN d1.id IS NULL THEN d.id ELSE d1.id END = d2.id INNER JOIN `groups` AS `g` ON d2.id = g.deliverable_id INNER JOIN `groupmembers` AS `gm` ON g.id = gm.group_id WHERE (g1.group_type = 100) AND (gm1.member_id = 1) AND (c.downstreamnode_id IS NULL OR d.restrict_access = 1) AND (g.group_type = 100 OR g.group_type = 110) AND (gm.member_id = 1) AND (d.deliverable_type = 110 OR d.deliverable_type = 100) GROUP BY CASE WHEN c.downstreamnode_id IS NULL THEN d.id ELSE c.downstreamnode_id END
Only problem is when I try to count the rows in a mysql query I only get 1 returned. below is the query
SELECT DISTINCT count(*) AS `rowCount` FROM `deliverable` AS `d` INNER JOIN `groups` AS `g1` ON d.id = g1.deliverable_id INNER JOIN `groupmembers` AS `gm1` ON g1.id = gm1.group_id LEFT JOIN `connection` AS `c` ON d.id = c.downstreamnode_id LEFT JOIN `deliverable` AS `d1` ON c.upstreamnode_id = d1.id INNER JOIN `deliverable` AS `d2` ON CASE WHEN d1.id IS NULL THEN d.id ELSE d1.id END = d2.id INNER JOIN `groups` AS `g` ON d2.id = g.deliverable_id INNER JOIN `groupmembers` AS `gm` ON g.id = gm.group_id WHERE (g1.group_type = 100) AND (gm1.member_id = 1) AND (c.downstreamnode_id IS NULL OR d.restrict_access = 1) AND (g.group_type = 100 OR g.group_type = 110) AND (gm.member_id = 1) AND (d.deliverable_type = 110 OR d.deliverable_type = 100) GROUP BY CASE WHEN c.downstreamnode_id IS NULL THEN d.id ELSE c.downstreamnode_id END
i generate this from by using the same 'select' that generated the first query but I reset the columns and add count in.
$this->getAdapter()->setFetchMode(Zend_Db::FETCH_ASSOC);
$select
->reset( Zend_Db_Select::COLUMNS)
->columns(array('count('.$column.') as rowCount'));
$rowCount = $this->getAdapter()->fetchOne($select);
This method works fine for all my other queries only this one i am having trouble with. I suspect it has something to do the 'CASE' I have in there but it is strange because I am getting the correct rows the the first query. Any ideas. Thanks.
FYI below are two queries that I have working successfully.
SELECT DISTINCT `po`.* FROM `post` AS `po` INNER JOIN `postinfo` AS `p` ON po.postinfo_id = p.id WHERE (p.creator_id = 1) ORDER BY `p`.`date_created` DESC
SELECT DISTINCT count(*) AS `rowCount` FROM `post` AS `po` INNER JOIN `postinfo` AS `p` ON po.postinfo_id = p.id WHERE (p.creator_id = 1) ORDER BY `p`.`date_created` DESC
In this one I have 4 rows returned in the first query and 'int 4' returned for the second one. Does anyone know why it doesnt work for the big query?
Move your DISTINCT.
SELECT COUNT(DISTINCT `po`.*) AS `rowCount` ...
Ok figured it out It was the GROUP BY that was causing only 1 result to be returned. Thanks Interrobang for you help I am sure that using DISTINCT incorrectly will have caused me a headache in the future.
Try using SQL_CALC_FOUND_ROWS in your query?
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows
Using SQL_CALC_FOUND_ROWS is mysql-specific, but it's pretty nice for getting a full record count even when your initial query contains a limit. Once you get the count, don't include SQL_CALC_FOUND_ROWS in subsequent queries for extra records since that will cause extra load on your query.
Your initial query would be:
SELECT SQL_CALC_FOUND_ROWS DISTINCT `d`.* FROM `deliverable` AS `d` INNER JOIN `groups` ...
You'll have to do a subsequent call after your initial query executes to get the count by doing a SELECT FOUND_ROWS().
If you do a little searching, you'll find someone who extended Zend_Db_Select to include this ability.

MySQL Query Optimisation

Looking for some help with optimising the query below. Seems to be two bottlenecks at the moment which cause it to take around 90s to complete the query. There's only 5000 products so it's not exactly a massive database/table. The bottlenecks are SQL_CALC_FOUND_ROWS and the ORDER BY statement - If I remove both of these it takes around a second to run the query.
I've tried removing SQL_CALC_FOUND_ROWS and running a count() statement, but that takes a long time as well..
Is the best thing going to be to use INNER JOIN's (which I'm not too familiar with) as per the following Stackoverflow post? Slow query when using ORDER BY
SELECT SQL_CALC_FOUND_ROWS *
FROM tbl_products
LEFT JOIN tbl_link_products_categories ON lpc_p_id = p_id
LEFT JOIN tbl_link_products_brands ON lpb_p_id = p_id
LEFT JOIN tbl_link_products_authors ON lpa_p_id = p_id
LEFT JOIN tbl_link_products_narrators ON lpn_p_id = p_id
LEFT JOIN tbl_linkfiles ON lf_id = p_id
AND (
lf_table = 'tbl_products'
OR lf_table IS NULL
)
LEFT JOIN tbl_files ON lf_file_id = file_id
AND (
file_nameid = 'p_main_image_'
OR file_nameid IS NULL
)
WHERE p_live = 'y'
ORDER BY p_title_clean ASC, p_title ASC
LIMIT 0 , 10
You could try reducing the size of the joins by using a derived table to retrieve the filtered and ordered products before joining. This assumes that p_live, p_title_clean and p_title are fields in your tbl_products table -
SELECT *
FROM (SELECT *
FROM tbl_products
WHERE p_live = 'y'
ORDER BY p_title_clean ASC, p_title ASC
LIMIT 0 , 10
) AS tbl_products
LEFT JOIN tbl_link_products_categories
ON lpc_p_id = p_id
LEFT JOIN tbl_link_products_brands
ON lpb_p_id = p_id
LEFT JOIN tbl_link_products_authors
ON lpa_p_id = p_id
LEFT JOIN tbl_link_products_narrators
ON lpn_p_id = p_id
LEFT JOIN tbl_linkfiles
ON lf_id = p_id
AND (
lf_table = 'tbl_products'
OR lf_table IS NULL
)
LEFT JOIN tbl_files
ON lf_file_id = file_id
AND (
file_nameid = 'p_main_image_'
OR file_nameid IS NULL
)
This is a "stab in the dark" as there is not enough detail in your question.

Help me optimize this query. Please

$query_index_neighborhood1 =
"SELECT areas_db.areas_name, areas_db.areas_id, neighborhoods_db.neighborhoods_id,
neighborhoods_db.neighborhoods_name, neighborhoods_db.neighborhoods_area_id,
areas_db.areas_state_id
FROM (
(
(
restaurants_db
INNER JOIN neighborhoods_db ON neighborhoods_db.neighborhoods_id=restaurants_db.restaurants_neighborhood
)
INNER JOIN areas_db ON areas_db.areas_id=neighborhoods_db.neighborhoods_area_id
)
INNER JOIN areas_db AS areas_db1 on areas_db1.areas_id=restaurants_db.restaurants_area
)
WHERE areas_db.areas_state_id=$mxstateid
GROUP BY neighborhoods_db.neighborhoods_id
ORDER BY areas_db.areas_id, neighborhoods_db.neighborhoods_name ASC";
As an interesting thought exercise, I came up with the following:
SELECT a.areas_name,
a.areas_id,
n.neighborhoods_id,
n.neighborhoods_name,
n.neighborhoods_area_id,
a.areas_state_id
FROM neighborhoods_db AS n
INNER JOIN areas_db AS a ON a.areas_id = n.neighborhoods_area_id
WHERE a.areas_state_id = $mxstateid
AND n.neighborhoods_id in (SELECT restaurants_neighborhood FROM restaurants_db)
ORDER BY a.areas_id, n.neighborhoods_name ASC
Also, table aliases are your friend.