Using this MySQL queries on my database:
SELECT movie.name, SUM(heroes.likes) AS 'success'
FROM heroebymovie JOIN
heroes
ON heroes.ID = heroebymovie.heroID JOIN
movie
ON movie.ID = heroebymovie.movieID
GROUP BY movie.ID
ORDER BY SUM(heroes.likes) DESC
I obtain this result:
|name |success |
|Avengers 2 |72317559 |
|Avengers |72317559 |
|Captain America : Civil War|67066832 |
I would like to display only the movies with the highest number of “success” (in this case “Avengers 2” and “Avengers”).
Can someone explain the way of doing it?
A simple way is using an having clause that filter for the max value ( in this case the ordered list of sum desc limit 1)
SELECT movie.name, SUM(heroes.likes) AS success
FROM heroebymovie JOIN heroes ON heroes.ID = heroebymovie.heroID
JOIN movie ON movie.ID = heroebymovie.movieID
GROUP BY movie.ID
HAVING success = (
SELECT SUM(heroes.likes)
FROM heroebymovie JOIN heroes ON heroes.ID = heroebymovie.heroID
JOIN movie ON movie.ID = heroebymovie.movieID
GROUP BY movie.ID
ORDER BY SUM(heroes.likes) DESC
LIMIT 1
)
ORDER BY SUM(heroes.likes) DESC
You are looking for a limit, but want to consider ties. MySQL supports the LIMIT clause, but unfortunately no accompanying ties expression.
In standard SQL you would simply add
FETCH 1 ROW WITH TIES;
and be done with it. (SQL Server does the same with TOP(1) WITH TIES.)
Another way would be to use standard SQL's MAX OVER: MAX(SUM(heroes.likes)) OVER() and only keep rows where the sum matches the maximum. Or use RANK OVER. But again, MySQL doesn't support either of these.
So your main option is to execute the query twice, like in this pseudo code:
select sum ... having sum = (select max(sum) ...)
An easy way to get the max of the sums in MySQL is to order by sums descending and limit the results to one row.
SELECT m.name, SUM(h.likes) AS "success"
FROM heroebymovie hm
JOIN heroes h ON h.ID = hm.heroID
JOIN movie m ON m.ID = hm.movieID
GROUP BY m.ID
HAVING SUM(h.likes) =
(
SELECT SUM(h2.likes)
FROM heroebymovie hm2
JOIN heroes h2 ON h2.ID = hm2.heroID
GROUP BY hm2.movieID
ORDER BY SUM(h2.likes) DESC
LIMIT 1
);
Related
Here is my SQL query:
SELECT s.name,
f.message,
e.timestamp,
e.result,
o.details
FROM event e
LEFT JOIN feed f ON e.id=f.id
LEFT JOIN oper o ON o.id=e.id
LEFT JOIN system s ON o.id=e.id
WHERE (e.date = ’15-06-2020’)
AND e.oper_id IN (SELECT id from oper
where state = ‘READY1’ or state = ‘READY2’ or state = ‘READY2’
group by state
order by state)
Now I have more then 3 results in my e.results table, however I wanted to take only recent 3 results (so sort on timestamp). So my final result from SQL should be only have recent 3 results.
I tried doing (select e.result from event ORDER BY DESC LIMIT 3) in place of e.result, which is not working.
Any idea how could I achieve this. I am querying MySQL.
firstly make the order in descending order and set limit for 3 in sql right after the order by clause.
change the column in subquery.
SELECT s.name,
f.message,
e.timestamp,
e.result,
o.details FROM event e
LEFT JOIN feed f ON e.id=f.id
LEFT JOIN oper o ON o.id=e.id
LEFT JOIN system s ON o.id=e.id
WHERE (e.date = ’15-06-2020’) AND
e.oper_id IN (SELECT id,state from oper
where state = ‘READY1’ or state = ‘READY2’
group by state order by state desc LIMIT 3)
try this.
I'm trying to pass a column from the outer query as shown below to the inner query in the WHERE clause and MySQL does not like it. I'm unsure how to rewrite this query to make it work.
The error message I am getting is Unknown column 'y.DateShipped' in where clause
What I am trying to do is to join to the row in the inner table with an EffectiveDate that is less than the DateShipped and also is the max EffectiveDate in the inner join (there can be multiple rows for the same group by with different EffectiveDate(s))
I would love to know how to get this working or rewrite it so that it will work. I am using MySQL 5.6, so I don't have window functions available otherwise I think that could work.
select
x.id,
y.id,
y.DateShipped
from Shipment y inner join
(select id, SourceId, DestinationId, SourcePPFContractId, EffectiveDate
from Relationship where EffectiveDate <= y.DateShipped order by
EffectiveDate desc limit 1) x
on x.DestinationId = y.DestinationCustomerId
and x.SourceId = y.OriginCustomerId
and x.SourcePPFContractId = y.OriginContractId;
The inner select (from Relationship) is executed first and then merged with the first select. That's why it doesn't work. You should move the DateShipped to the where clause of the first select:
select
x.id,
y.id,
y.DateShipped
from Shipment y inner join
(select id, SourceId, DestinationId, SourcePPFContractId, EffectiveDate
from Relationship order by
EffectiveDate desc limit 1) x
on x.DestinationId = y.DestinationCustomerId
and x.SourceId = y.OriginCustomerId
and x.SourcePPFContractId = y.OriginContractId
and x.EffectiveDate <= y.DateShipped;
You are attempting something called a lateral join -- and MySQL does not support those. Because you want only one column, you can use a correlated subquery:
select (select r.id
from Relationship r
where r.DestinationId = s.DestinationCustomerId and
r.SourceId = s.OriginCustomerId and
r.SourcePPFContractId = s.OriginContractId and
r.EffectiveDate <= s.DateShipped
order by r.EffectiveDate desc
limit 1
) as x_id,
s.id, s.DateShipped
from Shipment s ;
Note that I also changed the table aliases to be abbreviations for the table names -- so the query is easier to read.
you would need to list the shipment table in the sub query to be able to call it properly try:
select
x.id,
y.id,
y.DateShipped
from Shipment y inner join
(select id, SourceId, DestinationId, SourcePPFContractId, EffectiveDate
from Relationship, Shipment where EffectiveDate <= Shipment.DateShipped order by
EffectiveDate desc limit 1) x
on x.DestinationId = y.DestinationCustomerId
and x.SourceId = y.OriginCustomerId
and x.SourcePPFContractId = y.OriginContractId;
Some sql query gives me the following result:
As you can see, it already has GROUP BY.
So what I need? I need to group it again (by treatment_name) and count rows for each group. See more details on screenshot.
Here is full query:
SELECT
treatment_summaries.*
FROM `treatment_summaries`
INNER JOIN
`treatments`
ON
`treatments`.`treatment_summary_id` = `treatment_summaries`.`id`
AND
(treatment <> '' and treatment is not null)
INNER JOIN
`treatment_reviews`
ON
`treatment_reviews`.`treatment_id` = `treatments`.`id`
INNER JOIN
`conditions_treatment_reviews`
ON
`conditions_treatment_reviews`.`treatment_review_id` = `treatment_reviews`.`id`
INNER JOIN
`conditions` ON `conditions`.`id` = `conditions_treatment_reviews`.`condition_id`
INNER JOIN `conditions_treatment_summaries` `conditions_treatment_summaries_join`
ON
`conditions_treatment_summaries_join`.`treatment_summary_id` = `treatment_summaries`.`id`
INNER JOIN `conditions` `conditions_treatment_summaries`
ON `conditions_treatment_summaries`.`id` = `conditions_treatment_summaries_join`.`condition_id`
WHERE
`conditions`.`id` = 9
AND `conditions`.`id` IN (9)
AND (latest_review_id is not null)
GROUP BY
treatment_reviews.id
ORDER BY
treatment_summaries.reviews_count desc
LIMIT 20 OFFSET 0
Maybe there is another issue, cause GROUP BY should not leave same lines (for given column), but anyway you can wrap it like this:
SELECT * FROM ( YOUR_SQL_SELECT_WITH_EVERYTHING ) GROUP BY id
So the result you get will behave as another table and you can do all operations like GROUP BY again.
I'm trying to join two tables so I can easily order it, as one contains the names of items and the other doesn't. The tables:
user_games: UGID, UID, APPID, playtime
games_steam: APPID, name
my SQL so far:
SELECT user_games.*
FROM user_games
JOIN games_steam ON user_games.APPID = games_steam.APPID
WHERE user_games.UID = '76561197996836099'
GROUP BY user_games.APPID
ORDER BY games_steam.name ASC
LIMIT 0, 30
Just no idea how to get the name column into this aswell.
Is this what you are looking for?
SELECT user_games.*, games_steam.name
FROM user_games
JOIN games_steam
ON user_games.APPID = games_steam.APPID
WHERE user_games.UID = '76561197996836099'
GROUP BY user_games.APPID
ORDER BY games_steam.name ASC
LIMIT 0, 30
Below query is doing what I need:
SELECT assign.from_uid, assign.aid, assign.message, curriculum.asset,
curriculum.title, curriculum.description
FROM assignment assign
INNER JOIN curriculum_topics_assets curriculum
ON assign.nid = curriculum.asset
WHERE assign.to_uid = 13 AND assign.status = 1
GROUP BY assign.from_uid, assign.to_uid, assign.nid
ORDER BY assign.created DESC
Now I need to get the total count of rows of the result. For example if it is displaying 5 rows the o/p should be like My expected o/p. The query I tried is given below.
SELECT count(description) FROM assignment assign
INNER JOIN curriculum_topics_assets curriculum ON assign.nid = curriculum.asset
WHERE assign.to_uid = 13 AND assign.status = 1
GROUP BY assign.from_uid, assign.to_uid, assign.nid
ORDER BY assign.created DESC
My expected o/p:
count(*)
---------
5
My current o/p:
count(*)
---------
6
2
5
6
6
The easiest solution would be to
place your initial GROUP BY query in a subselect
select the amount of rows retrieved from this subselect
SQL Statement
SELECT COUNT(*)
FROM (
SELECT assign.from_uid
FROM assignment assign
INNER JOIN curriculum_topics_assets curriculum ON assign.nid = curriculum.asset
WHERE assign.to_uid = 13
AND assign.status = 1
GROUP BY
assign.from_uid
, assign.to_uid
, assign.nid
) q
Edit - why doesn't the original query return the results required
It did already prepared what was needed to get the correct result
Your query without grouping returns a resultset of 25 records (6+2+5+6+6)
From these 25 records, you have 5 unique combinations of from_uid, to_uid, nid
Now you don't want to count how many records each combination has (as you did in your example) but how many unique (distinct anyone?) combinations there are.
One solution to this is the subselect I presented but following equivalent statement using a DISTINCT clause might be more comprehensive.
SELECT COUNT(*)
FROM (
SELECT DISTINCT assign.from_uid
, assign.to_uid
, assign.nid
FROM assignment assign
INNER JOIN curriculum_topics_assets curriculum ON assign.nid = curriculum.asset
WHERE assign.to_uid = 13
AND assign.status = 1
) q
Note that my personal preference goes to the GROUP BY solution.
To get the number of rows for a query do:
SELECT COUNT(*) as RowCount FROM (--insert other query here--) s
In you example:
SELECT COUNT(*) as RowCount FROM (SELECT a.from_uid
FROM assignment a
INNER JOIN curriculum_topics_assets c ON a.nid = c.asset
WHERE a.to_uid = 13
AND a.status = 1
GROUP BY a.from_uid, a.to_uid, a.nid
) s
Note that I the dropped the stuff that has no effect on the number of rows to make the query run slightly faster.
You should use COUNT(*) instead of count(description). Look at: http://www.mysqlperformanceblog.com/2007/04/10/count-vs-countcol/