I have the following query that when executed, it just runs for hours and eventually the server times out.
SELECT l.mloc_id, COUNT( l.tabc_id ) , l.tabc_id, e.establishment_id, e.name, l.LocationName, l.naics, l.cuisine, l.cuisine2, l.service, l.www, l.owner, l.email, l.status
FROM vg_ydrink2.m_loc AS l
JOIN vg_ydk.permit_beverage AS pb ON ( l.tabc_id = pb.permit_code
AND pb.create_date = (
SELECT MAX( create_date )
FROM vg_ydk.permit_beverage
WHERE permit_code = l.tabc_id ) )
JOIN vg_ydk.establishment AS e ON ( pb.establishment_id = e.establishment_id )
GROUP BY l.mloc_id
ORDER BY `l`.`tabc_id` ASC
LIMIT 1 , 30
No errors are reported. It simply never gets completed.
The problem lies in the sub-select, because when removing it, the query executes without a problem. I also don't think it's the group function causing the issue, because I have tried keeping the subquery but removing the MAX and that did not work either.
Any thoughts?
Thank you in advance.
***EDIT: After having played with the create_date index a bit, I realized that due to the nature of its values, its cardinality is constantly very low. For that reason, it is not treated as an index by the query and as a result, too many rows are constantly loaded.
I have since changed the query altogether, so this is not an issue anymore. If anybody comes across a similar issue, make sure the used field is indexed properly. Analyze/optimize/repair your table if need be.
M.
Try this variation:
select l.mloc_id,
COUNT(l.tabc_id),
l.tabc_id,
e.establishment_id,
e.name,
l.LocationName,
l.naics,
l.cuisine,
l.cuisine2,
l.service,
l.www,
l.owner,
l.email,
l.status
from vg_ydrink2.m_loc as l
inner join (
select permit_code,
max(create_date) as MaxCreateDate
from vg_ydk.permit_beverage
group by permit_code
) pbm on l.tabc_id = pbm.permit_code
inner join vg_ydk.permit_beverage as pb on pbm.permit_code = pb.permit_code
and pbm.MaxCreateDate = pb.create_date
inner join vg_ydk.establishment as e on pb.establishment_id = e.establishment_id
group by l.mloc_id
order by `l`.`tabc_id` asc
LIMIT 1,
30
Related
I would like to select all login events and also the number of logins under one specific IP address by a MySQL query.
The Query that I have come up with is as follows. But I am afraid I have been missing something.
Hopefully one can see my mistake.
SELECT `pp_loginevent`.`loginevent_user`,
`pp_loginevent`.`loginevent_creationdate`,
`pp_loginevent`.`loginevent_ip`,
`pp_user`.`user_id`,
`pp_user`.`user_name`,
`pp_user`.`user_rights`,
`pp_user`.`user_active`,
`pp_license`.`license_name`
(SELECT COUNT(1)
FROM `pp_loginevent`
WHERE `loginevent_ip` = `pp_loginevent`.`loginevent_ip`
) AS `pp_loginevent`.`number_of_logins`
FROM `pp_loginevent`
LEFT JOIN `pp_user`
ON `pp_loginevent`.`loginevent_user` = `pp_user`.`user_id
LEFT JOIN `pp_license`
ON `pp_loginevent`.`loginevent_license` = `pp_license`.`license_id`
WHERE `loginevent_creationdate` LIKE '2019-%'
AND `user_rights` <= '6'
GROUP BY `loginevent_ip`
ORDER BY `loginevent_creationdate` DESC
What I am trying to do is to fetch the "column" number_of_logins and that should contain the number of logins made from a specific IP address.
You can't see anything wrong here:
`pp_license`.`license_name`
(SELECT COUNT(1) FROM `pp_loginevent` WHERE `loginevent_ip` = `pp_loginevent`.`loginevent_ip`) AS `pp_loginevent`.`number_of_logins`
?
While this won't resolve all the problems with this query, I think writing the query out this way makes one error very obvious:
SELECT e.loginevent_user
, e.loginevent_creationdate
, e.loginevent_ip
, u.user_id
, u.user_name
, u.user_rights
, u.user_active
, l.license_name
(SELECT COUNT(1)
FROM pp_loginevent
WHERE loginevent_ip = pp_loginevent.loginevent_ip) pp_loginevent.number_of_logins
FROM pp_loginevent e
JOIN pp_user u
ON u.user_id = e.loginevent_user
LEFT
JOIN pp_license l
ON l.license_id = e.loginevent_license
WHERE e.loginevent_creationdate >= '2019-01-01'
AND e.loginevent_creationdate < '2020-01-01'
AND user_rights <= 6
GROUP
BY loginevent_ip
ORDER
BY loginevent_creationdate DESC
In truth, as well as this syntax error, I suspect that there are other, logical, errors in this query.
Accordingly, see: Why should I provide an MCRE for what seems to me to be a very simple SQL query?
Okay, there are.. a number.. of questions on SO with the same title, but I couldn't think of how to be more specific.
The reason that this is confusing me is that returning more than one row is a desired effect of (one of) my sub queries
SELECT MAX(theCount) FROM
(SELECT FK_Hour, Count(FK_Hour) As theCount FROM
(Select FK_Hour
From slottime
INNER JOIN time ON slottime.FK_Hour = time.Hour
WHERE FK_Hour =
(SELECT time.Hour FROM time WHERE time.day=0 )
) As C
GROUP By FK_Hour
) AS counts;
I realise that time is a reserved word for MySQL - it is probably something I will have to rectify soon; though I doubt its the problem in this case.
The aim of the query is to select the maximum count of instances of particular hours where day = 0.
The problem is clearly:
WHERE FK_Hour = (SELECT time.Hour FROM time WHERE time.day=0 )
The simplest solution is to change = to in:
WHERE FK_Hour IN (SELECT time.Hour FROM time WHERE time.day=0 )
However, you might want to check your data to determine if this is what you really intend.
I have the following query, which was developed from a hint found online because of a problem with a GROUP BY returning the maximum value; but it's running really slowly.
Having looked online I'm seeing that WHERE IN (SELECT.... GROUP BY) is probably the issue, but, to be honest, I'm struggling to find a way around this:
SELECT *
FROM tbl_berths a
JOIN tbl_active_trains b on a.train_uid=b.train_uid
WHERE (a.train_id, a.TimeStamp) in (
SELECT a.train_id, max(a.TimeStamp)
FROM a
GROUP BY a.train_id
)
I'm thinking I possibly need a derived table, but my experience in this area is zero and it's just not working out!
you can move that to a SUBQUERY and also select only required columns instead of All (*)
SELECT a.train_uid
FROM tbl_berths a
JOIN tbl_active_trains b on a.train_uid=b.train_uid
JOIN (SELECT a.train_id, max(a.TimeStamp) as TimeStamp
FROM a
GROUP BY a.train_id )T
on a.train_id = T.train_id
and a.TimeStamp = T.TimeStamp
While working with following query on mysql, Its getting locked,
SELECT event_list.*
FROM event_list
INNER JOIN members
ON members.profilenam=event_list.even_loc
WHERE (even_own IN (SELECT frd_id
FROM network
WHERE mem_id='911'
GROUP BY frd_id)
OR even_own = '911' )
AND event_list.even_active = 'y'
GROUP BY event_list.even_id
ORDER BY event_list.even_stat ASC
The Inner query inside IN constraint has many frd_id, So because of that above query is slooow..., So please help.
Thanks.
Try this:
SELECT el.*
FROM event_list el
INNER JOIN members m ON m.profilenam = el.even_loc
WHERE el.even_active = 'y' AND
(el.even_own = 911 OR EXISTS (SELECT 1 FROM network n WHERE n.mem_id=911 AND n.frd_id = el.even_own))
GROUP BY el.even_id
ORDER BY el.even_stat ASC
You don't need the GROUP BY on the inner query, that will be making the database engine do a lot of unneeded work.
If you put even_own = '911' before the select from network, then if even_own IS 911 then it will not have to do the subquery.
Also why do you have a group by on the subquery?
Also run explain plan top find out what is taking the time.
This might work better:
( SELECT e.*
FROM event_list AS e
INNER JOIN members AS m ON m.profilenam = e.even_loc
JOIN network AS n ON e.even_own = n.frd_id
WHERE n.mem_id = '911'
AND e.even_active = 'y'
ORDER BY e.even_stat ASC )
UNION DISTINCT
( SELECT e.*
FROM event_list AS e
INNER JOIN members AS m ON m.profilenam = e.even_loc
WHERE e.even_own = '911'
AND e.even_active = 'y' )
ORDER BY e.even_stat ASC
Since I don't know whether the JOINs one-to-many (or what), I threw in DISTINCT to avoid dups. There may be a better way, or it may be unnecessary (that is, UNION ALL).
Notice how I avoid two things that are performance killers:
OR -- turned into UNION
IN (SELECT...) -- turned into JOIN.
I made aliases to cut down on the clutter. I moved the ORDER BY outside the UNION (and added parens to make it work right).
In the following query, I show the latest status of the sale (by stage, in this case the number 3). The query is based on a subquery in the status history of the sale:
SELECT v.id_sale,
IFNULL((
SELECT (CASE WHEN IFNULL( vec.description, '' ) = ''
THEN ve.name
ELSE vec.description
END)
FROM t_record veh
INNER JOIN t_state_campaign vec ON vec.id_state_campaign = veh.id_state_campaign
INNER JOIN t_state ve ON ve.id_state = vec.id_state
WHERE veh.id_sale = v.id_sale
AND vec.id_stage = 3
ORDER BY veh.id_record DESC
LIMIT 1
), 'x') sale_state_3
FROM t_sale v
INNER JOIN t_quarters sd ON v.id_quarters = sd.id_quarters
WHERE 1 =1
AND v.flag =1
AND v.id_quarters =4
AND EXISTS (
SELECT '1'
FROM t_record
WHERE id_sale = v.id_sale
LIMIT 1
)
the query delay 0.0057seg and show 1011 records.
Because I have to filter the sales by the name of the state as it would have to repeat the subquery in a where clause, I have decided to change the same query using joins. In this case, I'm using the MAX function to obtain the latest status:
SELECT
v.id_sale,
IFNULL(veh3.State3,'x') AS sale_state_3
FROM t_sale v
INNER JOIN t_quarters sd ON v.id_quarters = sd.id_quarters
LEFT JOIN (
SELECT veh.id_sale,
(CASE WHEN IFNULL(vec.description,'') = ''
THEN ve.name
ELSE vec.description END) AS State3
FROM t_record veh
INNER JOIN (
SELECT id_sale, MAX(id_record) AS max_rating
FROM(
SELECT veh.id_sale, id_record
FROM t_record veh
INNER JOIN t_state_campaign vec ON vec.id_state_campaign = veh.id_state_campaign AND vec.id_stage = 3
) m
GROUP BY id_sale
) x ON x.max_rating = veh.id_record
INNER JOIN t_state_campaign vec ON vec.id_state_campaign = veh.id_state_campaign
INNER JOIN t_state ve ON ve.id_state = vec.id_state
) veh3 ON veh3.id_sale = v.id_sale
WHERE v.flag = 1
AND v.id_quarters = 4
This query shows the same results (1011). But the problem is it takes 0.0753 sec
Reviewing the possibilities I have found the factor that makes the difference in the speed of the query:
AND EXISTS (
SELECT '1'
FROM t_record
WHERE id_sale = v.id_sale
LIMIT 1
)
If I remove this clause, both queries the same time delay... Why it works better? Is there any way to use this clause in the joins? I hope your help.
EDIT
I will show the results of EXPLAIN for each query respectively:
q1:
q2:
Interesting, so that little statement basically determines if there is a match between t_record.id_sale and t_sale.id_sale.
Why is this making your query run faster? Because Where statements applied prior to subSelects in the select statement, so if there is no record to go with the sale, then it doesn't bother processing the subSelect. Which is netting you some time. So that's why it works better.
Is it going to work in your join syntax? I don't really know without having your tables to test against but you can always just apply it to the end and find out. Add the keyword EXPLAIN to the beginning of your query and you will get a plan of execution which will help you optimize things. Probably the best way to get better results in your join syntax is to add some indexes to your tables.
But I ask you, is this even necessary? You have a query returning in <8 hundredths of a second. Unless this query is getting ran thousands of times an hour, this is not really taxing your DB at all and your time is probably better spent making improvements elsewhere in your application.