SUM of a secondSELECT statement - PHP - MySQL - php

I have the following query which works... but I need some changes:
SELECT
p.pid,
p.name,
GROUP_CONCAT( gC.leaguepoints ORDER BY leaguepoints DESC ) AS leaguepoints
FROM
golf_player p
LEFT JOIN
golf_card gC ON
p.pid = gC.pid
GROUP BY
p.pid
ORDER BY
p.name
DESC
What I really want is another property returned called totalleaguepoints which is a SUM of the most recent 20 league points in my table.
How do I add a limit to a group_concat?
It might be something like this?
SELECT
p.pid,
p.name,
GROUP_CONCAT( gC.leaguepoints ORDER BY leaguepoints DESC ) AS leaguepoints,
SUM(
SELECT
gC2.leaguepoints
FROM
golf_card gC2
WHERE
gC2.pid = p.pid
ORDER BY
leaguepoints
DESC
LIMIT 20
) AS totalleaguepoints
FROM
golf_player p
LEFT JOIN
golf_card gC ON
p.pid = gC.pid
GROUP BY
p.pid
ORDER BY
p.name
DESC
P.S, the above query does not run

Do you want just the top 20 league points for each player in the group_concat as well as the sum?
If so maybe use user variables:-
SELECT
p.pid,
p.name,
GROUP_CONCAT( gC.leaguepoints ORDER BY leaguepoints DESC ) AS leaguepoints,
SUM(gC.leaguepoints) AS totalleaguepoints
FROM golf_player p
LEFT JOIN
(
SELECT pid, leaguepoints, #Sequence:=IF(#PrevPid = pid, #Sequence + 1, 0) AS aSequence, #PrevPid := pid
FROM
(
SELECT pid, leaguepoints
FROM golf_card
ORDER BY pid, leaguepoints DESC
) Sub1
CROSS JOIN (SELECT #PrevPid := 0, #Sequence := 0) Sub2
) gC
ON p.pid = gC.pid AND aSequence < 20
GROUP BY p.pid
ORDER BY p.name DESC

Related

LIMIT LEFT join to last updated row from multiple rows

This is my code i am trying to left join the latest team data, not every piece of data. i have tried just using limit 1 but doesnt return anything
ORDER BY updated DESC LIMIT 1
this doesnt work
Any ideas?
$sql = "SELECT
events.id, events.time,events.status, events.home_team,events.away_team,events.league,
ht.id as home_id,ht.name as home_name,at.name as away_name,
statistics.home_goals,statistics.away_goals,statistics.time as game_time,
leagues.id as league_id,leagues.name as league_name,leagues.type as league_type,
country.name as country_name,country.logo,
hts.home_scored, ats.away_scored,
hts.home_conceeded,ats.away_conceeded,
hts.home_win,ats.away_win,
hts.home_15,ats.away_15,
hts.home_25,ats.away_25,
hts.home_btts, ats.away_btts,
hts.home_fts, ats.away_fts,
hts.home_cs, ats.away_cs,
hts.home_corners_for, ats.away_corners_for,
hts.home_corners_against, ats.away_corners_against,
hts.home_cards, ats.away_cards
FROM events
LEFT JOIN teams ht
ON ht.id = events.home_team
LEFT JOIN teams at
ON at.id = events.away_team
LEFT JOIN leagues
ON leagues.id = events.league
LEFT JOIN country
ON country.id=leagues.country
LEFT JOIN ( SELECT team,home_scored,home_conceeded,home_win,home_15,home_25,home_btts,home_fts,home_cs,home_corners_for,home_corners_against,home_cards FROM team_quick_stats ORDER BY updated DESC) hts
ON ht.id=hts.team
LEFT JOIN ( SELECT team,away_scored,away_conceeded,away_win,away_15,away_25,away_btts,away_fts,away_cs,away_corners_for,away_corners_against,away_cards FROM team_quick_stats ORDER BY updated DESC) ats
ON at.id=ats.team
LEFT JOIN statistics
ON statistics.event_id=events.id
WHERE (events.time BETWEEN $start AND $end) ORDER BY country.list_order, leagues.country ASC , leagues.id ASC, events.time ASC, home_name ASC";
Here's one way. Replace LEFT JOIN (SELECT team... etc....) ats with...
LEFT
JOIN
( SELECT x.team
, x.etc...
FROM team_quick_stats x
JOIN
( SELECT team
, MAX(updated) updated
FROM team_quick_stats
GROUP
BY team
) y
ON y.team = x.team
AND y.updated = x.updated
) ats...

Reference 'r1' not supported (reference to group function)

can me anyone help? i want to order users by total rating DESC, 2 ratings are in different tables , my sql:
SELECT dle_users.user_id, dle_users.user_group, dle_users.name,
dle_users.foto,
SUM(dle_comments.rating) as r1,
SUM(dle_post_extras.rating) as r2
FROM dle_users
JOIN dle_comments
ON dle_comments.user_id = dle_users.user_id
JOIN dle_post_extras ON dle_post_extras.user_id = dle_users.user_id
WHERE dle_comments.rating
AND dle_post_extras.rating > 0
GROUP BY dle_users.user_id
ORDER BY SUM(r1+r2) DESC
LIMIT 0,10
Aggregate before joining or your sums will be off:
SELECT u.user_id, u.user_group, u.name, u.foto,
COALESCE(c.r1, 0) as r1, COALESCE(e.r2, 0) as r2
FROM dle_users u LEFT JOIN
(SELECT user_id, SUM(rating) as r1
FROM dle_comments
GROUP BY user_id
) c
ON c.user_id = u.user_id LEFT JOIN
(SELECT user_id, SUM(rating) as r2
FROM dle_post_extras
WHERE rating > 0
GROUP BY user_id
) e
ON e.user_id = u.user_id
GROUP BY dle_users.user_id
ORDER BY COALESCE(r1, 0) + COALESCE(r2, 0) DESC
LIMIT 0, 10

query with dependent subqueries too slow

select mt.from_user, mt.to_user, mt.group_id, g.name, g.created_by as adminuser,
msg.*,
(
SELECT id
from messages
where t.thread_id = thread_id
and id NOT IN (
SELECT message_id from message_deleted
where user_id=275 and status='deleted' )
order by CreatedDate DESC
limit 1
) as msgid,
(
SELECT CreatedDate
from messages
where t.thread_id = thread_id
and id NOT IN (
SELECT message_id from message_deleted
where user_id=275 and status='deleted' )
order by CreatedDate DESC
limit 1
) as msgDate
from user_thread as t
left join message_thread as mt ON t.thread_id = mt.id
left join group_master as g ON mt.group_id = g.id
left join group_member as gm ON gm.group_id = g.id
left join messages as msg ON t.thread_id = msg.thread_id
where ( gm.user_id=275
or msg.from_id=275
or msg.to_id=275
)
and t.status = 'Active'
group by mt.id
order by msgDate DESC
This takes about 50 sec.
In above code, I have try to split above query and note that below subquery take too much time to execute. Can I convert subquery into join. please help me. I am stuck.please note that all tables which are joined are necessary.
(
SELECT id
from messages
where t.thread_id = thread_id
and id NOT IN (
SELECT message_id from message_deleted
where user_id=275 and status='deleted' )
order by CreatedDate DESC
limit 1
) as msgid,
(
SELECT CreatedDate
from messages
where t.thread_id = thread_id
and id NOT IN (
SELECT message_id from message_deleted
where user_id=275 and status='deleted' )
order by CreatedDate DESC
limit 1
) as msgDate
First, You are misusing a notorious MySQL extension to GROUP BY. This will probably cause your results to be unpredictable. Read this. https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
Second, You have a couple of nested dependent subqueries. The first of them is this.
(select id
from messages
where t.thread_id = thread_id
and id NOT IN (select message_id
from message_deleted
where user_id=275
and status='deleted')
order by CreatedDate DESC limit 1) as msgid
Such nested dependent subqueries perform notoriously badly. They're even worse when they contain LIMIT clauses. Your route to fixing this is refactoring into an independent query and then JOINing it.
This may work as a replacement for the query to find the most recent undeleted message on the thread.
SELECT MAX(m.id) id, m.thread_id
FROM messages m
LEFT JOIN message_deleted d
ON m.id = d.id
AND d.user_id = 275
AND d.status = 'deleted'
WHERE d.id IS NULL
GROUP BY m.thread_id
This uses the LEFT JOIN .... IS NULL pattern in place of NOT IN. It's faster. It uses the MAX(id) method of finding the most recent row in a table in place of the ORDER BY CreatedDate DESC LIMIT 1 method, which is also much faster. It's good because it's guaranteed to generate either 0 or 1 row per value of thread_id. That means you can use it in a LEFT JOIN ... ON ... thread_id operation and not add any rows to your result set.
You can test this subquery by running it. Then you JOIN it, as if it were a table, to the rest of your query, something like this.
SELECT whatever,
q.id, r.CreatedDate
FROM whatever
LEFT JOIN (
SELECT MAX(m.id) id, m.thread_id
FROM messages m
LEFT JOIN message_deleted d
ON m.id = d.id
AND d.user_id = 275
AND d.status = 'deleted'
WHERE d.id IS NULL
GROUP BY m.thread_id
) q ON q.id = t.id
LEFT JOIN messages r ON r.id = q.id
The second LEFT JOIN operation here is used to retrieve the CreatedDate value of the newest undeleted message from the messages table.

Having problems writing mysql query joining 4 tables

I have a query (which partially works) looking like the following:
SELECT i.vehicle_id, i.user_id, i.make, i.model, i.year, i.state, i.price, i.class, i.fuel, i.mileage, i.mileage_type, i.featured, i.published, i.creation, i.status, m.vehicle_id, m.type, m.src, a.user_id, a.inventory_status, a.country, s.user_id, s.currency_iso, s.currency_code
FROM `cms_dealer_inventory` AS `i`,
`cms_dealer_inventory_media` AS `m`,
`cms_dealer_account` AS `a`,
`cms_dealer_setting` AS `s`
WHERE i.make='chevrolet'
AND i.model='camaro'
AND i.year='2014'
AND (i.mileage <= 200000 )
AND i.published='1'
AND a.inventory_status='1'
AND m.vehicle_id=i.vehicle_id
AND m.type='exterior'
AND a.user_id=i.user_id
AND s.user_id=i.user_id
AND a.country='DE'
GROUP BY i.vehicle_id
ORDER BY i.featured DESC, i.price ASC, i.state DESC, i.make ASC
The problem is, the cms_dealer_inventory_media may or may not contain images (bind by vehicle_id). I know the problem is with my WHERE statement in which I am specifically saying m.vehicle_id=i.vehicle_id AND m.type='exterior' but, it causes entries with no images to be ignore.
What I need is a query which makes the m.vehicle_id=i.vehicle_id run IF there are results to cms_dealer_inventory_media.
You should use left join
SELECT i.vehicle_id, i.user_id, i.make, i.model, i.year, i.state, i.price, i.class, i.fuel, i.mileage, i.mileage_type, i.featured, i.published, i.creation, i.status, m.vehicle_id, m.type, m.src, a.user_id, a.inventory_status, a.country, s.user_id, s.currency_iso, s.currency_code
FROM `cms_dealer_inventory` AS `i` left join
`cms_dealer_inventory_media` AS `m` on m.vehicle_id=i.vehicle_id
AND m.type='exterior' left join
`cms_dealer_account` AS `a` on a.inventory_status='1'
AND a.user_id=i.user_id AND a.country='DE' left join
`cms_dealer_setting` AS `s` ON s.user_id=i.user_id
WHERE i.make='chevrolet'
AND i.model='camaro'
AND i.year='2014'
AND (i.mileage <= 200000 )
AND i.published='1'
GROUP BY i.vehicle_id
ORDER BY i.featured DESC, i.price ASC, i.state DESC, i.make ASC
If you change your query to use the more modern explicit joins, you could use left joins:
SELECT i.vehicle_id, i.user_id, i.make, i.model, i.year, i.state, i.price, i.class, i.fuel, i.mileage, i.mileage_type, i.featured, i.published, i.creation, i.status, m.vehicle_id, m.type, m.src, a.user_id, a.inventory_status, a.country, s.user_id, s.currency_iso, s.currency_code
FROM `cms_dealer_inventory` AS `i`
LEFT JOIN `cms_dealer_inventory_media` AS `m` ON m.vehicle_id=i.vehicle_id
LEFT JOIN `cms_dealer_account` AS `a` ON a.user_id=i.user_id
LEFT JOIN `cms_dealer_setting` AS `s` ON s.user_id=i.user_id
WHERE i.make='chevrolet'
AND i.model='camaro'
AND i.year='2014'
AND (i.mileage <= 200000 )
AND i.published='1'
AND a.inventory_status='1'
AND m.type='exterior'
AND a.country='DE'
GROUP BY i.vehicle_id
ORDER BY i.featured DESC, i.price ASC, i.state DESC, i.make ASC
you will have to use the join properly
in your case you need all the records from cms_dealer_inventory
so join will be cms_dealer_inventory left outer cms_dealer_inventory_media

select n posts per category in a single query

In my home page I show different posts from different categories.
My current implementation is to call query_posts many times (once per category)
How can I use one query to pull out the data?
My tries
1 - this method works(ignore the ugly very long sql,I have many categories...)
Thanks the post: http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
( SELECT *
FROM `wp_posts` p,`wp_term_relationships` rel
WHERE rel.object_id = p.ID
AND rel.term_taxonomy_id = '3'
ORDER BY p.post_date DESC
LIMIT 2)
UNION ALL
( SELECT *
FROM `wp_posts` p,`wp_term_relationships` rel
WHERE rel.object_id = p.ID
AND rel.term_taxonomy_id = '4'
ORDER BY p.post_date DESC
LIMIT 2)
SELECT i.*
FROM wp_term_relationships rel
INNER JOIN (
SELECT p.*, rel2.*
FROM wp_posts p
INNER JOIN wp_term_relationships rel2
ON (rel2.object_id = p.ID)
WHERE rel2.term_taxonomy_id = rel.term_taxonomy_id
ORDER BY p.post_date DESC
LIMIT 2 OFFSET 0 ) i ON (i.object_id = rel.object_id)
WHERE rel.term_taxonomy_id IN ('3','4')
ORDER BY i.term_taxonomy_id ASC, i.post_date DESC

Categories