I have a principal requet with 2 requets in. I have a problem in my second nested query, I have a condition on id and if I made my request id = 10 takes a long time to execute, so if I replace it by id LIKE 10 my request execute in one second.
Here the request:
SELECT SQL_NO_CACHE contact_groupe.id_contact_groupe
FROM toto.contact_groupe
LEFT JOIN toto.`contact` AS `contact`
ON ((toto.contact_groupe.id_contact_groupe = toto.contact.id_contact_groupe))
LEFT JOIN toto.`project` AS `project`
ON ((toto.contact_groupe.id_contact_groupe = toto.project.id_contact_groupe)
AND ( toto.project.id_project
IN (
SELECT MAX(toto.project.id_project)
FROM toto.project
WHERE ( toto.contact_groupe.id_contact_groupe = toto.project.id_contact_groupe )
) ))
LEFT JOIN toto.`phase` AS `phase`
ON ((project.id_phase = toto.phase.id_phase))
LEFT JOIN sql_base.`user` AS `user_suivi`
ON ((toto.contact_groupe.id_user_suivi = user_suivi.id_user))
WHERE ( en_attente = '0' AND contact_groupe.id_contact_groupe
IN (
SELECT DISTINCT(contact_groupe.id_contact_groupe)
FROM toto.contact_groupe
LEFT JOIN toto.`contact` AS `contact`
ON ((toto.contact_groupe.id_contact_groupe = toto.contact.id_contact_groupe)
LEFT JOIN toto.`source_contact_groupe` AS `source_contact_groupe`
ON ((toto.contact_groupe.id_contact_groupe = toto.source_contact_groupe.id_contact_groupe))
LEFT JOIN toto.`project` AS `project`
ON ((toto.contact_groupe.id_contact_groupe = toto.project.id_contact_groupe))
LEFT JOIN toto.`remarque` AS `remarque`
ON ((toto.contact_groupe.id_contact_groupe = toto.remarque.id_contact_groupe))
LEFT JOIN toto.`project_type_construction_options` AS `project_type_construction_options`
ON ((project.id_project = toto.project_type_construction_options.id_project))
LEFT JOIN toto.`project_concurrent` AS `project_concurrent`
ON ((project.id_project = toto.project_concurrent.id_project))
LEFT JOIN toto.`telephone` AS `telephone`
ON ((contact.id_contact = toto.telephone.id_contact))
WHERE ( en_attente = '0' AND ( toto.project.id_project = '10' ) AND toto.contact_groupe.id_entreprise = '2' )
)
AND toto.contact_groupe.id_entreprise = '2' )
ORDER BY toto.contact_groupe.id_contact_groupe ASC
the line is the following problem toto.project.id_project = '10' and I don't understand why the time to execute request is so different between = and LIKE
Let's start with your subquery. Those 17 lines that you've written are functionally identical to this, so why not use this instead?
SELECT DISTINCT g.id_contact_groupe
FROM contact_groupe g
JOIN project p
ON p.id_contact_groupe = g.id_contact_groupe
WHERE g.en_attente = 0
AND p.id_project = 10
AND g.id_entreprise = 2
Related
I have the following sentence, that returns the error
Unknown column targets.ID_TARGET in where clause
and I can't find any solution. Could you guys help?
The proposal is update 'sw_automatic' for each row with the value that th subquery provides (0 or 1)
update bt_pry_targets targets
set targets.sw_automatic = (
(
SELECT (CASE WHEN Task.ID_TP_TASKS_GROUPS = 694 THEN '0' ELSE '1' END) AS TYPE_TASK,
Task.ID_TASK FROM bt_tasks AS Task
INNER JOIN bt_pry_cmp_workflows AS BtCmpWorkflows ON (Task.ID_PRY_CMP_WORKFLOW = BtCmpWorkflows.ID_PRY_CMP_WORKFLOW)
INNER JOIN bt_pry_components AS PryComponent ON (PryComponent.ID_PRY_COMPONENT = BtCmpWorkflows.ID_PRY_COMPONENT )
INNER JOIN bt_components AS Component ON (PryComponent.ID_COMPONENT = Component.ID_COMPONENT)
INNER JOIN bt_pry_targets AS PryTarget ON (PryComponent.ID_TARGET = PryTarget.ID_TARGET)
INNER JOIN bt_flows AS Flows ON (Flows.ID_FLOW = Task.ID_FLOW)
WHERE Flows.SW_END_DEPENDENCE = 1
AND PryTarget.ID_TARGET = targets.ID_TARGET
GROUP BY Task.ID_TASK) )
where targets.sw_automatic is null;
In you subquery the column targets.ID_TARGET in not visible
so you could try using you subquery as a join table for updated
update bt_pry_targets targets
inner join (
SELECT (CASE WHEN Task.ID_TP_TASKS_GROUPS = 694 THEN '0' ELSE '1' END) AS TYPE_TASK,
Task.ID_TASK FROM bt_tasks AS Task
INNER JOIN bt_pry_cmp_workflows AS BtCmpWorkflows ON (Task.ID_PRY_CMP_WORKFLOW = BtCmpWorkflows.ID_PRY_CMP_WORKFLOW)
INNER JOIN bt_pry_components AS PryComponent ON (PryComponent.ID_PRY_COMPONENT = BtCmpWorkflows.ID_PRY_COMPONENT )
INNER JOIN bt_components AS Component ON (PryComponent.ID_COMPONENT = Component.ID_COMPONENT)
INNER JOIN bt_pry_targets AS PryTarget ON (PryComponent.ID_TARGET = PryTarget.ID_TARGET)
INNER JOIN bt_flows AS Flows ON (Flows.ID_FLOW = Task.ID_FLOW)
WHERE Flows.SW_END_DEPENDENCE = 1
AND PryTarget.ID_TARGET = targets.ID_TARGET
GROUP BY Task.ID_TASK
) t on t.PryTarget = targets.ID_TARGET
AND targets.sw_automatic is null
set targets.sw_automatic = t.TYPE_TASK
I would like to search a keyword from the result of the subquery. In my subquery I already filtered the grants I need from different category required. Now I need to search the keyword in title for those results. Or is there efficient way to do this query because my work is not working after days stuck?
I tried working on the IN but still did not get it right.
SELECT DISTINCT gt.grant_id, gt.*,
infra.infra_name,
infrasub.infrasub_name,
lga.lga_name,
stream.stream_id,
stream.stream_n,
stream.stream_dept,
stream.stream_desc
FROM
grant_tbl AS gt
LEFT JOIN grant_details AS gd
ON (
gt.grant_id = gd.grant_id
)
LEFT JOIN infra_sub_tbl AS infrasub
ON (
infrasub.infra_sub_id = gd.infrasub_id
)
LEFT JOIN infra_tbl AS infra
ON (
infra.infra_id = gd.infra_id
)
LEFT JOIN lga_tbl AS lga
ON (
lga.lga_id = gd.lga_id
)
LEFT JOIN streams_tbl AS stream
ON (
stream.stream_id = gd.stream_id
)
WHERE gt.grant_id IN
(
SELECT DISTINCT gd.grant_id, CONCAT(gt.grant_name,"|",gt.grant_desc,"|",gt.keywords)
FROM grant_details AS gd
LEFT JOIN grant_tbl AS gt
ON gt.grant_id = gd.grant_id
WHERE gd.lga_id = 1
OR gd.lga_id = 2
AND gd.stream_id = 1
OR gd.stream_id = 2
GROUP BY gt.grant_id
)
my result should narrow down from my subquery. display only with matching keyworkds
You can use EXISTS instead of IN,
SELECT DISTINCT gt.grant_id, gt.*,
infra.infra_name,
infrasub.infrasub_name,
lga.lga_name,
stream.stream_id,
stream.stream_n,
stream.stream_dept,
stream.stream_desc
FROM grant_tbl AS gt
LEFT JOIN grant_details AS gd ON gt.grant_id = gd.grant_id
LEFT JOIN infrasub_tbl AS infrasub ON infrasub.infrasub_id = gd.infrasub_id
LEFT JOIN infra_tbl AS infra ON infra.infra_id = gd.infra_id
LEFT JOIN lga_tbl AS lga ON lga.lga_id = gd.lga_id
LEFT JOIN stream_tbl AS stream ON stream.stream_id = gd.stream_id
WHERE exists
(
SELECT DISTINCT gd.grant_id,CONCAT(gt2.grant_name,"|",gt2.grant_desc,"|",gt2.keywords)
FROM grant_details AS gd
LEFT JOIN grant_tbl AS gt2 ON gt2.grant_id = gd.grant_id
WHERE (gd.lga_id = 10 OR gd.lga_id = 20) AND (gd.stream_id = 100 OR gd.stream_id = 200)
and gt.grant_id=gt2.grant_id
GROUP BY gt.grant_id
)
Hope this helps.
I am using InnoDB. From this question, I found out that I have to specify the length if I want to add index to columns which type is TEXT.
But after successfully adding index, the performance for the select query stay the same. Anyone know why? I did check the index with show index from tableName and the index did exist.
So it was the last two table EventResultsFinalSummary and EventResultsPrelims.
CREATE OR REPLACE VIEW ScheduleView AS
SELECT s.ScheduleID, e.EventRound, e.EventRoundsID, e.EventID, e.NumberCouplesInRound, n.NumberOnBack, eic.EventName AS 'Division',
CONCAT(a1.FirstName, ' ', a1.LastName, ' - ', a2.FirstName, ' ', a2.LastName) AS 'Couple',
s.SessionID AS 'Session', erfs.CouplePlace, c.CoupleID,
s.Timeslot, s.SubFloor ,s.itemDuration,s.HeatNumber, o.ActivityName, st.StudioName AS 'DanceStudio', a.AgeName AS 'Age', s.competition_id, erp.CoupleVotes
FROM Schedule AS s
LEFT JOIN EventRounds AS e ON s.EventRoundID = e.EventRoundsID AND s.competition_id = e.competition_id
LEFT JOIN OtherActivities AS o ON s.OtherActivitiesID = o.OtherActivitiesID AND s.competition_id = o.competition_id
LEFT JOIN EntriesEvents AS ee ON e.EventID = ee.EventID AND e.EventRound <= ee.EventRound AND e.Competition_id = ee.Competition_id
LEFT JOIN Couples AS c ON ee.EntryID = c.CoupleID AND ee.Competition_id = c.Competition_id
LEFT JOIN NumSysComps AS n ON c.CompetitorIDMan = n.CompetitorIDMan AND c.Competition_id = n.Competition_id
LEFT JOIN Attendees AS a1 ON c.CompetitorIDMan = a1.AttendeeID AND c.Competition_id = a1.Competition_id
LEFT JOIN Attendees AS a2 ON c.CompetitorIDLady = a2.AttendeeID AND c.Competition_id = a2.Competition_id
LEFT JOIN Studios AS st ON a1.StudioID = st.StudioID AND a1.Competition_id = st.Competition_id
LEFT JOIN EventsInComp AS eic ON eic.EventID = e.EventID AND eic.Competition_id = e.Competition_id
LEFT JOIN ProAmSingleDanceEvents AS psd ON eic.ProAmSingleDanceEventID = psd.ProAmSingleDanceEventID AND eic.Competition_id = psd.Competition_id
LEFT JOIN ProAmMultiDanceEvents AS pmd ON eic.ProAmMultiDanceEventID = pmd.ProAmMultiDanceEventID AND eic.Competition_id = pmd.Competition_id
LEFT JOIN Ages AS a ON (
psd.AgeID = a.AgeID AND psd.Competition_id = a.Competition_id
OR
pmd.AgeID = a.AgeID AND pmd.Competition_id = a.Competition_id
)
LEFT JOIN EventResultsFinalSummary AS erfs ON e.EventID = erfs.EventID AND c.CoupleID = erfs.CoupleID AND s.Competition_id = erfs.Competition_id
LEFT JOIN EventResultsPrelims AS erp ON e.EventID = erp.EventID AND erp.EventRound = e.EventRound AND c.CoupleID = erp.CoupleID AND s.Competition_id = erp.Competition_id
ORDER BY s.ScheduleID;
I added index to the column that I joined.
EventID, CoupleId, Competition_id for EventResultsFinalSummary and EventID, EventRound, Competition_id for EventResultsPrelims by using query like following.
My question is that when those columns have type like varchar or int, the select * query will only take 1s. But it take 26s when the type is Text.
ALTER TABLE `EventResultsPrelims` ADD INDEX(`EventID`(6));
I have MySQL query currently selecting and joining 13 tables and finally grouping ~60k rows. The query without grouping takes ~0ms but with grouping the query time increases to ~1.7sec. The field, which is used for grouping is primary field and is indexed. Where could be the issue?
I know group by without aggregate is considered invalid query and bad practise but I need distinct base table rows and can not use DISTINCT syntax.
The query itself looks like this:
SELECT `table_a`.*
FROM `table_a`
LEFT JOIN `table_b`
ON `table_b`.`invoice` = `table_a`.`id`
LEFT JOIN `table_c` AS `r1`
ON `r1`.`invoice_1` = `table_a`.`id`
LEFT JOIN `table_c` AS `r2`
ON `r2`.`invoice_2` = `table_a`.`id`
LEFT JOIN `table_a` AS `i1`
ON `i1`.`id` = `r1`.`invoice_2`
LEFT JOIN `table_a` AS `i2`
ON `i2`.`id` = `r2`.`invoice_1`
JOIN `table_d` AS `_u0`
ON `_u0`.`id` = 1
LEFT JOIN `table_e` AS `_ug0`
ON `_ug0`.`user` = `_u0`.`id`
JOIN `table_f` AS `_p0`
ON ( `_p0`.`enabled` = 1
AND ( ( `_p0`.`role` < 2
AND `_p0`.`who` IS NULL )
OR ( `_p0`.`role` = 2
AND ( `_p0`.`who` = '0'
OR `_p0`.`who` = `_u0`.`id` ) )
OR ( `_p0`.`role` = 3
AND ( `_p0`.`who` = '0'
OR `_p0`.`who` = `_ug0`.`group` ) ) ) )
AND ( `_p0`.`action` = '*'
OR `_p0`.`action` = 'read' )
AND ( `_p0`.`related_table` = '*'
OR `_p0`.`related_table` = 'table_name' )
JOIN `table_a` AS `_e0`
ON ( ( `_p0`.`related_id` = 0
OR `_p0`.`related_id` = `_e0`.`id`
OR `_p0`.`related_user` = `_e0`.`user`
OR `_p0`.`related_group` = `_e0`.`group` )
OR ( `_p0`.`role` = 0
AND `_e0`.`user` = `_u0`.`id` )
OR ( `_p0`.`role` = 1
AND `_e0`.`group` = `_ug0`.`group` ) )
AND `_e0`.`id` = `table_a`.`id`
JOIN `table_d` AS `_u1`
ON `_u1`.`id` = 1
LEFT JOIN `table_e` AS `_ug1`
ON `_ug1`.`user` = `_u1`.`id`
JOIN `table_f` AS `_p1`
ON ( `_p1`.`enabled` = 1
AND ( ( `_p1`.`role` < 2
AND `_p1`.`who` IS NULL )
OR ( `_p1`.`role` = 2
AND ( `_p1`.`who` = '0'
OR `_p1`.`who` = `_u1`.`id` ) )
OR ( `_p1`.`role` = 3
AND ( `_p1`.`who` = '0'
OR `_p1`.`who` = `_ug1`.`group` ) ) ) )
AND ( `_p1`.`action` = '*'
OR `_p1`.`action` = 'read' )
AND ( `_p1`.`related_table` = '*'
OR `_p1`.`related_table` = 'table_name' )
JOIN `table_g` AS `_e1`
ON ( ( `_p1`.`related_id` = 0
OR `_p1`.`related_id` = `_e1`.`id`
OR `_p1`.`related_user` = `_e1`.`user`
OR `_p1`.`related_group` = `_e1`.`group` )
OR ( `_p1`.`role` = 0
AND `_e1`.`user` = `_u1`.`id` )
OR ( `_p1`.`role` = 1
AND `_e1`.`group` = `_ug1`.`group` ) )
AND `_e1`.`id` = `table_a`.`company`
WHERE `table_a`.`date_deleted` IS NULL
AND `table_a`.`company` = 4
AND `table_a`.`type` = 1
AND `table_a`.`date_composed` >= '2016-05-04 14:43:55'
GROUP BY `table_a`.`id`
The ORs kill performance.
This composite index may help: INDEX(company, type, date_deleted, date_composed).
LEFT JOIN table_b ON table_b.invoice = table_a.id seems to do absolutely nothing other than slow down the processing. No fields of table_b are used or SELECTed. Since it is a LEFT join, it does not limit the output. Etc. Get rid if it, or justify it.
Ditto for other joins.
What happens with JOIN and GROUP BY: First, all the joins are performed; this explodes the number of rows in the intermediate 'table'. Then the GROUP BY implodes the set of rows.
One technique for avoiding this explode-implode sluggishness is to do
SELECT ...,
( SELECT ... ) AS ...,
...
instead of a JOIN or LEFT JOIN. However, that works only if there is zero or one row in the subquery. Usually this is beneficial when an aggregate (such as SUM) can be moved into the subquery.
For further discussion, please include SHOW CREATE TABLE.
I have a query that JOINs some tables to get a list of products including prices, images, country etc.
"product_images" table can have zero or more images but only the default image should be returned. My problem is that in any case the query should return a result for the product even if there is no image in the "product_images" table for that particular product.
The first query example will return a row for each product but just return a random image:
SELECT `cp`.`category_id`, `p`.`id`, `p`.`master`, `p`.`status`, `p`.`sortorder`, `p`.`sku`, `p`.`stock`, `pd`.`name`, `pd`.`short_description`, `pd`.`description`, `pd`.`slug`, `pi`.`image`, `pi`.`path`
FROM `categories_products` AS `cp`
JOIN `products` AS `p` ON (`cp`.`product_id` = `p`.`id`)
JOIN `product_descriptions` AS `pd`
ON (`pd`.`product_id` = `p`.`id`)
LEFT JOIN `product_images` AS `pi`
ON (`pi`.`product_id` = `p`.`id`)
WHERE `cp`.`category_id` = 34
AND `pd`.`locale_id` = 1
AND `p`.`master` = '0'
AND `p`.`status` = '1'
AND `p`.`accessible` = '1'
AND `pd`.`status` = '1'
GROUP BY `p`.`id`
ORDER BY `p`.`sortorder`
Below query will return the default image. But if there is no image in "product_images" the row for that product will not be retrieved. The only difference here is this part: "AND pi.preset = 1"
SELECT `cp`.`category_id`, `p`.`id`, `p`.`master`, `p`.`status`, `p`.`sortorder`, `p`.`sku`, `p`.`stock`, `pd`.`name`, `pd`.`short_description`, `pd`.`description`, `pd`.`slug`, `pi`.`image`, `pi`.`path`
FROM `categories_products` AS `cp`
JOIN `products` AS `p` ON (`cp`.`product_id` = `p`.`id`)
JOIN `product_descriptions` AS `pd`
ON (`pd`.`product_id` = `p`.`id`)
LEFT JOIN `product_images` AS `pi`
ON (`pi`.`product_id` = `p`.`id`)
WHERE `cp`.`category_id` = 34
AND `pi`.`preset` = 1
AND `pd`.`locale_id` = 1
AND `p`.`master` = '0'
AND `p`.`status` = '1'
AND `p`.`accessible` = '1'
AND `pd`.`status` = '1'
GROUP BY `p`.`id`
ORDER BY `p`.`sortorder`
`pi`.`preset` = 1
in WHERE defeats your goal (your LEFT JOIN behaves like INNER ) . Move it to ON:
LEFT JOIN `product_images` AS `pi`
ON (`pi`.`product_id` = `p`.`id` AND `pi`.`preset` = 1)
You may prefer to use a subquery:
LEFT JOIN (SELECT * FROM product_images WHERE preset = 1) AS pi ON ...
Otherwise, the WHERE clause is applied to the entire query, and if there's no image, WHERE pi.preset=1 will reduce your search set to zero rows.