How to expand MySQL subquery/join to include all rows - mysql

This query below is perfect in producing the result for horse_id = 1 ... but I want to do this for all horses in the database. Can anyone share with me how to tweak this query so I can do that?
SELECT figures.entry_id,
max(figures.beyer)
FROM
( SELECT hrdb_lines.horse_id,
hrdb_entries.entry_id,
hrdb_lines.beyer
FROM hrdb_entries
INNER JOIN hrdb_lines
ON hrdb_lines.horse_id = hrdb_entries.horse_id
WHERE hrdb_lines.horse_id = 1
ORDER BY hrdb_lines.line_date DESC
LIMIT 2
) as figures
Perhaps I'm doing it all wrong too.

I think the following would generate the desired results:
SELECT `entry_id`, `beyer`
FROM (SELECT hrdb_entries.entry_id,
MAX( hrdb_lines.beyer )
FROM hrdb_entries
INNER JOIN hrdb_lines
ON hrdb_lines.horse_id = hrdb_entries.horse_id
GROUP BY hrdb_lines.horse_id
ORDER BY hrdb_lines.line_date DESC
) AS figures

If I'm understanding your question, something like this should be close:
SELECT
figures.horse_id,
figures.entry_id,
max(figures.beyer)
FROM
(SELECT
hrdb_lines.horse_id,
hrdb_entries.entry_id,
hrdb_lines.beyer
FROM hrdb_entries
INNER JOIN hrdb_lines ON hrdb_lines.horse_id = hrdb_entries.horse_id
ORDER BY hrdb_lines.line_date DESC
) as figures
GROUP BY figures.horse_id
One option to limit the MAX to just the most recent 2 beyer fields is to add a row number to the results and only include rows 1 and 2.
SELECT
figures.horse_id,
figures.entry_id,
max(figures.beyer)
FROM
(SELECT
#rn:=if(#prev_horse_id=horse_id,#rn+1,1) rn,
hrdb_lines.horse_id,
hrdb_entries.entry_id,
hrdb_lines.beyer,
#prev_horse_id:=hrdb_lines.horse_id
FROM hrdb_entries
INNER JOIN hrdb_lines ON hrdb_lines.horse_id = hrdb_entries.horse_id
INNER JOIN (SELECT #rn:=0) r
ORDER BY hrdb_lines.horse_id, hrdb_lines.line_date DESC
) as figures
WHERE rn <= 2
GROUP BY figures.horse_id

Related

Searching and Sorting Using MySQL Inner Join

I guess I can't explain my problem properly. I want to explain this to you with a picture.
Picture 1
In the first picture you can see the hashtags in the trend section. These hashtags are searched for the highest total and it is checked whether the date has passed. If valid data is available, the first 5 hashtags are taken.
Picture 2
In the second picture, it is checked whether the posts in the hashtag are in the post, if any, the oldest date value is taken, LIMIT is set to 1 and the id value from the oyuncular table is matched with sid. Thus, the name of the person sharing can be accessed.
Picture 3
My English is a little bad, I hope I could explain it properly.
SELECT
social_trend.hashtag,
social_trend.total,
social_trend.tarih,
social_post.sid,
social_post.tarih,
social_post.post,
oyuncular.id,
oyuncular.isim
FROM
social_trend
INNER JOIN
social_post
ON
social_post.post LIKE '%social_trend.hashtag%' ORDER BY social_post.tarih LIMIT 1
INNER JOIN
oyuncular
ON
oyuncular.id = social_post.sid
WHERE
social_trend.tarih > UNIX_TIMESTAMP() ORDER BY social_trend.total DESC LIMIT 5
YOu should use a sibquery
and add a proper join between subqiery and social_trend
(i assumed sing both sid)
SELECT
social_trend.hashtag,
social_trend.total,
social_trend.tarih,
t.sid,
t.tarih,
t.post,
oyuncular.id,
oyuncular.isim
FROM (
select social_post.*
from social_post
INNER JOIN social_trend ON social_post.post LIKE concat('%',social_trend.hashtag,'%' )
ORDER BY social_post.tarih LIMIT 1
) t
INNER JOIN social_trend ON social_trend.hashtag= t.post
INNER JOIN oyuncular ON oyuncular.id = t.sid
WHERE
social_trend.tarih > UNIX_TIMESTAMP() ORDER BY social_trend.total DESC LIMIT 5
but looking to your new explanation and img seems you need
SELECT
t.hashtag,
t.total,
t.tarih_trend,
t.sid,
t.tarih,
t.post,
oyuncular.id,
oyuncular.isim
FROM (
select social_post.sid
, social_post.tarih
, social_post.post
, st.hashtag
, st.total
, st.tarih tarih_trend
from social_post
INNER JOIN (
select * from social_trend
WHERE social_trend.tarih > UNIX_TIMESTAMP()
order by total DESC LIMIT 5
) st ON social_post.post LIKE concat('%',st.hashtag,'%' )
ORDER BY social_post.tarih LIMIT 5
) t
INNER JOIN oyuncular ON oyuncular.id = t.sid

How to display only the multiple maximal values of my result table?

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
);

GROUP BY ordering

I have the following query in mysql:
select territory_id, platform_type_id, p.store_url
from main_itemmaster m
inner join main_iteminstance i on m.id=i.master_id
inner join main_territorypricing p on p.item_id=i.id
inner join main_territorypricingavail a on a.tp_id=p.id
where imdb_url = 'http://imdb.com/title/tt1576422/'
group by platform_type_id
Which gives me the following:
territory_id platform_type_id store_url
US Amazon http://www.amazon.com/dp/B00EQIHJAG
PT ITUNES https://itunes.apple.com/pt/movie/id582142080
However, I want to do a GROUP BY to return the territory_id="US" first if that exists. How would I do that?
This is one way I tried which looks quite dirty but does work in the version of mysql I'm using:
select * from
(select territory_id, platform_type_id, p.store_url from main_itemmaster m
inner join main_iteminstance i on m.id=i.master_id
inner join main_territorypricing p on p.item_id=i.id
inner join main_territorypricingavail a on a.tp_id=p.id
where imdb_url = 'http://imdb.com/title/tt1576422/'
order by territory_id='us' desc
) x group by platform_type_id
Which gives:
territory_id platform_type_id store_url
US Amazon http://www.amazon.com/dp/B00EQIHJAG
US ITUNES https://itunes.apple.com/us/movie/id582142080
Which is the correct result set I'm looking to get.
Here is a link to a SQL fiddle. I condensed all the data into one table to focus on the GROUP BY statement: http://sqlfiddle.com/#!9/81c3b6/2/0
So from the comments and the addition of the SqlFiddle it actually seems like you want to create a partitioned row number with a precedence on US per platform and then select the first record. One way of doing partitioned Row Numbers in mysql is to use variables here is an example:
SELECT
territory_id
,platform_type_id
,store_url
FROM
( SELECT
*
,#PlatFormRowNum:= IF(#prevplatform = platform_type_id, #PlatFormRowNum + 1, 1) as PlatformRowNum
,#prevplatform:= platform_type_id
FROM
main_itemmaster m
CROSS JOIN (SELECT #prevplatform:='',#PlatFormRowNum=0) var
ORDER BY
platform_type_id
,CASE WHEN territory_id = 'US' THEN 0 ELSE 1 END
,territory_id
) t
WHERE
t.PlatformRowNum = 1
ORDER BY
t.platform_type_id
SQL Fiddle: http://sqlfiddle.com/#!9/81c3b6/12
Basically this partitions the row number by platform, orders US before any other territory and then selects the first row foreach platform. The one question/trick is how do you choose which to return when US is not available for the platform simply the ascending alphabetical order of the territory_id?

Left join order by

I have property pictures in table with their sort_order starting from 0 to number of pictures.
What I would like to do is select pictures but I would like it to start from 2.
My approach was:
SELECT * FROM property_photos AS pp1
JOIN property_photos AS pp2 ON pp1.p_id = pp2.p_id
where pp2.sort_order =2
and pp2.sort_order <2
and pp1.sort_order >2
and pp1.p_id = 3
So what I am trying to gain here is the sort order would be like 2,0,1,3,4,5,6,7
so I need a self join but my query doesn't work
you don't need a join on this,
SELECT *
FROM property_photos
WHERE p_id = 3
ORDER BY (sort_order = 2) DESC, sort_order

How to count using LEFT JOIN?

I need to make a list with the company that scans the most things... I've got two tables, Exhibitors and Leads
Leads contain each "action" that every exhibitors does. Sometimes, in the Exhibitors table, there's two accounts for the same company. For example, PepsiCO might have two accounts.
The key/col that link both is called ExhibitorID.
I need to retrieve the top 20 with the most leads (so COUNT(*) in leads) but I need to group by Company in Exhibitors table.
Curerntly I am using this :
SELECT t2.ExhibitorID, t2.Company, t2.Username, t1.Count
FROM exhibitors AS t2
, ( SELECT ExhibitorID, COUNT( * ) AS Count
FROM leads AS l
WHERE l.ContractorID = 100
AND l.ShowID = "20120228AB"
GROUP BY l.ExhibitorID
ORDER BY COUNT(*) DESC
LIMIT 20 ) AS t1
WHERE t2.ExhibitorID = t1.ExhibitorID
ORDER BY t1.Count DESC
But it doesn't group by company. Thanks for all your help.
select e.exhibitorid, count(l.leadid)
from leads l
inner join exhibitors on e.exhibitorid = l.exhibitorid
and l.showid = "20120228AB" and l.contractorid = 100
group by e.exhibitorid
order by count(l.contractorid) DESC
limit 20;
If there are ties, this will still only return the top 20. So if you want ties then there appears to be a MySql workaround here MySQL's alternative to T-SQL's WITH TIES
SELECT
e.Company,
COUNT(l.LeadId) AS Actions
FROM
Exhibitors AS e
LEFT JOIN Leads AS l
ON l.ExhibitorID = e.ExhibitorID
AND l.ContractorID = 100
AND l.ShowID = "20120228AB"
GROUP BY e.Company
ORDER BY Actions DESC
LIMIT 20;
You could group on Company and join on ExhibitorID:
select e.Company
, count(distinct l.LeadID) as LeadCount
from Exhibitors e
join Leads l
on l.ExhibitorID = e.ExhibitorID
and l.ShowID = "20120228AB"
and l.ContractorID = 100
group by
e.Company
order by
LeadCount DESC
limit 20