Could somebody help me optimize this query? I have a table with huge data. Could somebody help me optimize without using sub query?
SELECT user_id, scheduled_on_date
FROM
(SELECT user_id, scheduled_on_date
FROM `calls`
ORDER BY scheduled_on_date DESC) AS cinner
GROUP BY user_id
Output expected is:
What I need is the only rows of the users with their last scheduled_date for call.
You can rewrite your query as follows
SELECT c.user_id, c.scheduled_on_date ,other_fields_max_per_group
FROM `calls` c
JOIN (SELECT user_id, MAX(scheduled_on_date) scheduled_on_date
FROM `calls`
GROUP BY user_id) AS cc
ON(c.user_id =cc.user_id AND c.scheduled_on_date =cc.scheduled_on_date)
Add compound index
ALTER TABLE calls ADD INDEX `test` (user_id ,scheduled_on_date )
If there you only want the greatest date and user id you can use only
SELECT user_id, MAX(scheduled_on_date) scheduled_on_date
FROM `calls`
GROUP BY user_id
select c1.*
from calls c1 left join call c2 on c1.user_id = c2.user_id
and c1.scheduled_on_date < c2.scheduled_on_date
where c2.user_id is null;
If you wanted to optimize it further
make sure you have index on (user_id,scheduled_on_date)
get only the required columns
Related
Can you help me, please? I spent about 2 hours to understand what is wrong, but still don't.
SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name
'id'
select count(*) as aggregate
from (
select `cities`.*,
`cities`.`id` as `id`,
`cities`.`country_id` as `country_id`,
`cities`.`name` as `name`,
`cities`.`alias` as `alias`,
`cities`.`active_frontend` as `active_frontend`
from `cities`
where (
cities.alias in (
select `alias`
from `cities`
group by `alias`
having COUNT(`alias`) > 1
)
)
) count_row_table
Don't ask me what the hell is going on please. Biggest part of this query is generated by Laravel.
If I delete this part:
where
(cities.alias IN (SELECT alias FROM cities GROUP BY alias HAVING
COUNT(alias) > 1))
It will work. But I need this part af.
The issue is with cities.*.
But you can simplify your query to:
select sum(cnt) as cnt
from (
select COUNT(alias) as cnt
from cities
group by alias
having COUNT(alias) > 1
) t
and avoid re-reading your table because in the end, all your need is total number of rows for which alias has more than one row.
You don't need to materialize a subquery for this. You can do:
select count(*)
from cities c
where exists (select 1 from cities c2 where c2.alias = c.alias and c2.id <> c.id);
With an index on cities(alias, id), this should have better performance.
This following query take 1-2 seconds for querying.
SELECT updated, COUNT( * ) count
FROM v2_subscription
WHERE ss_id IN (SELECT MAX(ss_id) ss_id FROM v2_subscription GROUP BY uid, card_id)
while the subquery do take only few milliseconds.
SELECT MAX(ss_id) ss_id FROM v2_subscription GROUP BY uid, card_id
I do have index on uid, card_id and both uid, card_id
It's my sql and i have no idea how to optimize this.
Please advise,
Try this, May be it would help, let me know, if it does.
SELECT a.updated, COUNT( * ) count
FROM v2_subscription a
inner join v2_subscription b
on a.ss_id = max(b.ss_id)
GROUP BY b.uid, b.card_id
Or perhaps this
SELECT a.updated, COUNT( * ) count
FROM v2_subscription a
inner join v2_subscription b
on a.ss_id = (SELECT MAX(b.ss_id) b.ss_id FROM v2_subscription b GROUP BY b.uid, b.card_id)
Finally i have found the solution beside #arkumar above answer.
Adding "ORDER BY ss_id" inside the subquery also do the trick
Since without order by, the result of subquery do not have index.
I have the following mysql query:
SELECT id, sum(views) as total_views
FROM table
WHERE id IN (1,2,3)
GROUP BY id
ORDER BY total_views ASC
If only id 1,3 are found in the database, i still want id 2 to appear, with total_views being set to 0.
Is there any way to do that? This cannot use any other table.
This query hard-codes the list of possible IDs using a sub-query consisting of unions... it then left joins this set of ids to the table containing the information to be counted.
This will preserve an ID in your results even if there are no occurrences:
SELECT ids.id, sum(views) as total_views
FROM (
SELECT 1 AS ID
UNION ALL SELECT 2 AS ID
UNION ALL SELECT 3 AS ID
) ids
LEFT JOIN table
ON table.ID = ids.ID
GROUP BY ids.id
ORDER BY total_views ASC
Alternately, if you had a numbers table, you could do the following query:
SELECT numbers.number, sum(views) as total_views
FROM
numbers
LEFT JOIN table
ON table.ID = ids.ID
WHERE numbers.number IN (1, 2, 3)
GROUP BY numbers.number
ORDER BY total_views ASC
Here's an alternative to Micheal's solution (not a bad solution, mind you -- even with "a lot" of ID's), so long as you're not querying against a cluster.
create temporary table __ids (
id int unsigned primary key
) engine=MEMORY;
insert into __ids (id) values
(1),
(2),
(3)
;
SELECT table.id, sum(views) as total_views
FROM __ids left join table using (id)
GROUP BY table.id
ORDER BY total_views ASC
And if your query becomes complex, I could even conceive of it running more efficiently this way. But, if I were you, I'd benchmark this option with Michael's ad-hoc UNION'ed table option using real data.
in #Michael's answer, if you do have a table with the ids you care about, you can use it as "ids" in place of Michael's in-line data.
Check this fiddle... http://www.sqlfiddle.com/#!2/a9392/3
Select B.ID, sum(A.views) sum from tableB B
left outer join tableA A
on B.ID = A.ID
group by A.ID
also check
http://www.sqlfiddle.com/#!2/a1bb7/1
try this
SELECT id
(CASE 1
IF EXISTS THEN views = mytable.views END
IF NOT EXIST THEN views = 0 END
CASE 2
IF EXISTS THEN views = mytable.views END
IF NOT EXIST THEN views = 0 END
CASE 3
IF EXISTS THEN views = mytable.views END
IF NOT EXIST THEN views = 0 END), sum(views) as total_views
FROM mytable
WHERE id IN (1,2,3)
GROUP BY id
ORDER BY total_views ASC
Does it have to be rows or could you pivot the data to give you one row and a column for every id?
SELECT
SUM(IF (id=1, views, 0)) views_1,
SUM(IF (id=2, views, 0)) views_2,
SUM(IF (id=3, views, 0)) views_3
FROM table
I have 2 tables. MySql
users : A_ID,name
event : B_ID, A_ID,cat_id,date
Now I want to get all users , who participated more at events on a given period of time, and need to add based on category too. I am doing something like this :
select name from users ,
(select A_id, count(*)
from event
where date<=givendate
group by A_id
order by count(*) desc ) e
where users.A_id=e.a_id
limit 0,5
Is there any easy and prof way to write that script ?
Thanks
Your query looks OK apart from a few minor points:
Your ORDER BY and LIMIT should be in the outer select otherwise the order of the results is indeterminate.
Use the JOIN keyword to join two tables.
Try this:
SELECT u.name
FROM users AS u
JOIN
(
SELECT A_id, COUNT(*) AS cnt
FROM event
WHERE date <= givendate
AND cat_id = 42
GROUP BY A_id
) AS e
USING (A_id)
ORDER BY e.cnt DESC
LIMIT 5
I have a table as follows:
ident_nr|proj_nr|start_time|
----------------------------
05.26.73|0000001|1116936920|
09.56.df|0000002|1213431234|
11.ac.12|0000003|1236485758|
98.er.df|0000001|1287789755|
70.12.5n|0000001|1011245554|
33.dt.vp|0000003|1239125544|
And I want a result like this:
ident_nr|proj_nr|start_time|
----------------------------
98.er.df|0000001|1287789755|
09.56.df|0000002|1213431234|
33.dt.vp|0000003|1239125544|
where proj_nr is in asc order and start time with the max value.
Note: ident_nr is unique and proj_nr could have multiple ident_nr.
Database: MySQL.
Is there an SQL query that could achieve this result?
Thanks
SELECT t.ident_nr, t.proj_nr, t.start_time
FROM YourTable t
INNER JOIN (SELECT proj_nr, MAX(start_time) AS MaxTime
FROM YourTable
GROUP BY proj_nr) q
ON t.proj_nr = q.proj_nr
AND t.start_time = q.MaxTime
ORDER BY t.proj_nr;
SELECT t1.*
FROM table AS t1
INNER JOIN (
SELECT proj_nr, MAX(start_time) AS MaxTime
FROM table
GROUP BY proj_nr) AS t2
ON (t1.proj_nr = t2.proj_nr AND t1.start_time = t2.MaxTime)
Your criteria seems to be MAX(start_time) in your sample data. If not, please be more detailed in your question about what you want.