Cannot see mySQL COUNT from 3rd table - mysql

I have posted another message like this. But none helped. So I have done some more reading and I have this code which works to a point:
EDIT NEW VERSION & NEW ISSUE
SELECT i.*, o.organ_name, o.organ_logo, vtable.*
FROM heroku_056eb661631f253.op_ideas i
JOIN
(SELECT
COUNT(v.agree) as agree,
COUNT(v.disagree = 1 or null) as disagree,
COUNT(v.obstain = 1 or null) as abstain
FROM op_idea_vote v
) AS vtable
LEFT JOIN op_organs o ON i.post_type = o.organs_id
There is only 1 row in the op_idea_vote table, and 3 in the op_ideas table. But it's giving each row the total in each op_ideas row
EDIT WORKING SOLUTION
Thanks to WayneC, here is the working code:
SELECT i.*, o.organ_name, o.organ_logo, vtable.*
FROM heroku_056eb661631f253.op_ideas i
JOIN
(SELECT v.idea_Id,
COUNT(v.agree = 1 or null) as agree,
COUNT(v.disagree = 1 or null) as disagree,
COUNT(v.obstain = 1 or null) as abstain
FROM op_idea_vote v
GROUP BY v.idea_id
) AS vtable ON vtable.idea_id = i.idea_id
LEFT JOIN op_organs o ON i.post_type = o.organs_id
WHERE idea_geo = 'International';

Try this
SELECT i.*, o.organ_name, o.organ_logo, vtable.*
FROM heroku_056eb661631f253.op_ideas i
JOIN
(SELECT
COUNT(v.agree) as agree,
COUNT(v.disagree = 1 or null) as disagree,
COUNT(v.obstain = 1 or null) as abstain
FROM op_idea_vote v
GROUP BY v.idea_id
) AS vtable ON vtable.idea_id = i.idea_id
LEFT JOIN op_organs o ON i.post_type = o.organs_id
The answer below was missing the group by, and join condition for vtable

Here's your original query
SELECT i.*, o.organ_name, o.organ_logo
FROM heroku_056eb661631f253.op_ideas i
JOIN
(SELECT
COUNT(v.agree) as agree,
COUNT(v.disagree = 1 or null) as disagree,
COUNT(v.obstain = 1 or null) as abstain
FROM op_idea_vote v, op_ideas i
WHERE v.idea_id = i.idea_id
) AS vtable
LEFT JOIN op_organs o ON i.post_type = o.organs_id
vtable is a subquery masquerading as a table you're joining to - in terms of getting the fields to be returned with the query results, it's no different from joining a normal table. You have to select the fields you want returned in the main query, or they won't be returned.
SELECT i.*, o.organ_name, o.organ_logo, vtable.*
FROM heroku_056eb661631f253.op_ideas i
JOIN
(SELECT
COUNT(v.agree) as agree,
COUNT(v.disagree = 1 or null) as disagree,
COUNT(v.obstain = 1 or null) as abstain
FROM op_idea_vote v, op_ideas i
WHERE v.idea_id = i.idea_id
) AS vtable
LEFT JOIN op_organs o ON i.post_type = o.organs_id

Related

Group by not getting the expected results in mysql

I have the next query:
SELECT DISTINCT
bt.name, b.id
FROM
ports po,
cities c,
provinces p,
countries co,
states s,
translations t,
element_types et,
languages l,
boat_models bm,
boat_types bt,
boats b
JOIN
boat_prices bprf ON b.id = bprf.boat_id
AND bprf.checkin_date IS NULL
AND bprf.duration_id IS NULL
WHERE
t.element_translation = 'España'
AND et.name = 'Country'
AND s.name = 'confirmed'
AND s.id = b.state_id
AND l.locale = 'es'
AND t.language_id = l.id
AND t.element_type_id = et.id
AND t.element_id = p.country_id
AND c.province_id = p.id
AND po.city_id = c.id
AND b.port_id = po.id
AND bm.id = b.boat_model_id
AND bt.id = bm.boat_type_id
That is working perfectly and returning 9 rows:
'BOAT_TYPE_CATAMARAN','13707'
'BOAT_TYPE_SAILBOAT','13700'
'BOAT_TYPE_SAILBOAT','13701'
'BOAT_TYPE_SAILBOAT','13702'
'BOAT_TYPE_SAILBOAT','13703'
'BOAT_TYPE_SAILBOAT','13704'
'BOAT_TYPE_SAILBOAT','13705'
'BOAT_TYPE_SAILBOAT','13706'
'BOAT_TYPE_SAILBOAT','13708'
I want to group the results by boat type and get the number of boats per type.
However, when I do:
SELECT DISTINCT
bt.name, COUNT(b.id) AS num_boats
FROM
ports po,
cities c,
provinces p,
countries co,
states s,
translations t,
element_types et,
languages l,
boat_models bm,
boat_types bt,
boats b
JOIN
boat_prices bprf ON b.id = bprf.boat_id
AND bprf.checkin_date IS NULL
AND bprf.duration_id IS NULL
WHERE
t.element_translation = 'España'
AND et.name = 'Country'
AND s.name = 'confirmed'
AND s.id = b.state_id
AND l.locale = 'es'
AND t.language_id = l.id
AND t.element_type_id = et.id
AND t.element_id = p.country_id
AND c.province_id = p.id
AND po.city_id = c.id
AND b.port_id = po.id
AND bm.id = b.boat_model_id
AND bt.id = bm.boat_type_id
GROUP BY bt.name
ORDER BY bt.name
I´m getting:
'BOAT_TYPE_CATAMARAN','241'
'BOAT_TYPE_SAILBOAT','1928'
but according to the first query, I´m expecting
'BOAT_TYPE_CATAMARAN','1'
'BOAT_TYPE_SAILBOAT','8'
What am I missing?
I suspect that you want:
SELECT bt.name, COUNT(DISTINCT b.id) AS num_boats
FROM ...
WHERE ...
GROUP BY bt.name
ORDER BY bt.name
That is: move the DISTINCT within the COUNT() rather than directly in the SELECT.
Generally speaking, DISTINCT and GROUP BY do not go along well together; DISTINCT is already aggregation in essence, so mixing both is usually not relevant.
Note that your syntax uses old-school, implicit joins (with a comma in the FROM clause): you should be using standard joins (with the ON keyword), whose syntax has been state-of-the-art for decades.
You are doing a distinct in your first query so you are 'hiding' a lot if rows that gets doubled because of your join.

How to fix MySQL query not to return nulls

Here is my query,
SELECT
p.pcode,
p.productName,
s.pcode,
MAX(s.in_stock) AS opening_stock,
SUM(s.soldQty) AS sold_qty,
MIN(s.remaining_qty) AS closing_stock,
s.date_created,
g.pcode,
g.qty,
g.received_qty,
g.received_on
FROM tbl_products p
LEFT JOIN tbl_sold_items s
ON p.pcode = s.pcode
LEFT JOIN tbl_shop_gr_items g
ON p.pcode = g.pcode
WHERE
(s.date_created = '2019-09-27') AND
(g.received_on = '2019-09-27')
GROUP BY p.pcode
stock_report_sample
When the above query is executed it return null values when one of the selected table doesn't have the item id for that particular day. I want it to show a list of all the items(products) available even though the item has not been sold or received so that in those instances it should show zero (0)
Maybe you can use ISNULL to show zero value if NULL
SELECT
p.pcode,
p.productName,
s.pcode,
ISNULL(MAX(s.in_stock),0) AS opening_stock,
ISNULL(SUM(s.soldQty),0) AS sold_qty,
ISNULL(MIN(s.remaining_qty),0) AS closing_stock,
s.date_created,
g.pcode,
g.qty,
g.received_qty,
g.received_on
FROM tbl_products p
LEFT JOIN tbl_sold_items s ON p.pcode = s.pcode
LEFT JOIN tbl_shop_gr_items g ON p.pcode = g.pcode
WHERE(s.date_created = '2019-09-27') AND (g.received_on = '2019-09-27')
GROUP BY p.pcode
SELECT
p.pcode,
p.productName,
CASE
WHEN gr_rows IS NULL AND sl_rows IS NULL THEN 0
WHEN gr_rows > 0 AND sl_rows IS NULL THEN received_stock
WHEN gr_rows > 0 AND sl_rows > 0 THEN opening_stock
ELSE 0
END AS op_stock,
IFNULL(received_stock, 0),IFNULL(sold_stock, 0)
FROM tbl_products p
LEFT JOIN (
SELECT COUNT(r.ID) AS gr_rows,r.pcode,r.received_on,SUM(r.received_qty) AS received_stock
FROM tbl_shop_gr_items r
WHERE r.received_on = '2019-10-03'
GROUP BY r.pcode
)AS r ON p.pcode = r.pcode
LEFT JOIN (
SELECT COUNT(s.ID) AS sl_rows,s.pcode,s.date_created,SUM(s.soldQty) AS sold_stock
FROM tbl_sold_items s
WHERE s.date_created = '2019-10-03'
GROUP BY s.pcode
)AS s ON p.pcode = s.pcode
LEFT JOIN (
SELECT t.ID,t.pcode,t.date_created,t.remaining_qty AS opening_stock
FROM tbl_sold_items t
WHERE t.date_created > '2019-10-03'
GROUP BY t.pcode ORDER BY t.ID
)AS t ON p.pcode = t.pcode
The above code has solved my issue

Combine query that relies on resultset of another

I run this query to get 20 random items from my wordpress database based on things like rating, category, etc
SELECT (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY RAND()
LIMIT 20
Then, for each result of the random items, I want to find a corresponding item that is very similar to the random item (around the same rating) but not identical and also one the user has not seen:
SELECT ABS($site_rating-(A.user_votes/A.user_voters)) as diff, (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category ,IFNULL(F.count,0) as count
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
LEFT JOIN (
SELECT *,COUNT(*) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as F ON (A.post_id = F.post_id_winner OR A.post_id = F.post_id_loser)
WHERE
E.name = '$category' AND
B.ID <> '$post_id' AND
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY count ASC, diff ASC
LIMIT 1
Where the following php variables refer to the result of the previous query
$post_id = $result['post_id'];
$category = $result['category'];
$site_rating = $result['site_rating'];
and $_SERVER['REMOTE_ADDR'] refers to the user's IP.
Is there a way to combine the first query with the 20 additional queries that need to be called to find corresponding items, so that I need just 1 or 2 queries?
Edit: Here is the view that simplifies the joins
CREATE VIEW `versus_random` AS
SELECT (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
My attempt now with the view:
SELECT post_id,
(
SELECT INNER_TABLE.post_id
FROM `versus_random` as INNER_TABLE
WHERE
INNER_TABLE.post_id <> OUTER_TABLE.post_id
ORDER BY (SELECT COUNT(*) FROM `versus` WHERE ip = '54' AND (INNER_TABLE.post_id = post_id_winner OR INNER_TABLE.post_id = post_id_loser)) ASC
LIMIT 1
) as innerquery
FROM `versus_random` as OUTER_TABLE
ORDER BY RAND()
LIMIT 20
However the query just timesout and freezes my mysql.
I think it should work like this, but I don't have any Wordpress at hand to test it. The second query that gets the related post is embedded in the other query, when it gets just the related_post_id. The whole query is turned into a subquery itself, given the alias 'X' (although you are free to use 'G', if you want to continue your alphabet.)
In the outer query, the tables for posts and data-article are joined again (RA and RP) to query the relevant fields of the related post, based on the related_post_id from the inner query. These two tables are left joined (and in reverse order), so you still get the main post if no related post was found.
SELECT
X.site_rating,
X.post_id,
X.post_author,
X.post_date,
X.category,
RA.user_votes / RA.user_voters as related_post_site_rating,
RP.ID as related_post_id,
RP.post_author as related_post_author,
RP.post_date as related_post_date,
RP.name as related_category,
FROM
( SELECT
(A.user_votes/A.user_voters) as site_rating,
B.ID as post_id, B.post_author, B.post_date,E.name as category,
( SELECT
RB.ID as post_id
FROM `wp_gdsr_data_article` as RA
INNER JOIN `wp_posts` as RB ON (RA.post_id = RB.id)
INNER JOIN wp_term_relationships RC ON (RB.ID = RC.object_id)
INNER JOIN wp_term_taxonomy RD ON (RC.term_taxonomy_id = RD.term_taxonomy_id)
INNER JOIN wp_terms RE ON (RD.term_id = RE.term_id)
LEFT JOIN (
SELECT *,COUNT(*) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as RF ON (RA.post_id = RF.post_id_winner OR RA.post_id = RF.post_id_loser)
WHERE
RE.name = E.name AND
RB.ID <> B.ID AND
RB.post_type = 'post' AND
RB.post_status = 'publish' AND
RD.taxonomy='category' AND
RE.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY count ASC, diff ASC
LIMIT 1) as related_post_id
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY RAND()
LIMIT 20
) X
LEFT JOIN `wp_posts` as RP ON RP.id = X.related_post_id
LEFT JOIN `wp_gdsr_data_article` as RA.post_id = RP.id
I can't test my proposal so take it with the benefit of the doubt. Anyway i hope it could be a valid starting point for some of the issues faced.
I can not imagine a solution that does not pass through a temporary table, cabling onerous computations present in your queries. You could also have the goal to not interfere with the randomization of the first phase. In the following I try to clarify.
I'll start with these rewritings:
-- first query
SELECT site_rating, post_id, post_author, post_date, category
FROM POSTS_COMMON
ORDER BY RAND()
LIMIT 20
-- second query
SELECT ABS(R.site_rating_A - R.site_rating_B) as diff, R.site_rating_B as site_rating, P.post_id, P.post_author, P.post_date, P.category, F.count
FROM POSTS_COMMON AS P
INNER JOIN POSTS_RATING_DIFFS AS R ON (P.post_id = R.post_id_B)
LEFT JOIN (
/* post_id_winner, post_id_loser explicited; COUNT(*) NULL treatment anticipated */
SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as F ON (P.post_id = F.post_id_winner OR P.post_id = F.post_id_loser)
WHERE
P.category = '$category'
AND R.post_id_A = '$post_id'
ORDER BY count ASC, diff ASC
LIMIT 1
with:
SELECT A.post_id_A, B.post_id_B, A.site_rating as site_rating_A, B.site_rating as site_rating_B
INTO POSTS_RATING_DIFFS
FROM POSTS_COMMON as A, POSTS_COMMON as B
WHERE A.post_id <> B.post_id AND A.category = B.category
CREATE VIEW POSTS_COMMON AS
SELECT A.ID as post_id, A.user_votes, A.user_voters, (A.user_votes / A.user_voters) as site_rating, B.post_author, B.post_date, E.name as category
FROM wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.post_id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
POSTS_COMMON isolates a common view between the two queries.
With POSTS_RATING_DIFFS, a temporary table populated with the ratings combinations and diffs, we have "the trick" of transforming the inequality join criteria on post_id(s) in an equality one (see R.post_id_A = '$post_id' in the second query).
We also take advantage of a temporary table in having precomputed ratings for the combinatory explosion of A.post_id <> B.post_id (with post category equality), and moreover being useful for other sessions.
Also extracting the RAND() ordering in a temporary table could be advantageous. In this case we could limit the ratings combinations and diffs only on the 20 randomly chosen.
Original limiting to one single row in the dependent second level query is done by mean of ordering and limit statements.
The proposed solution avoids elaborating a LIMIT 1 on an ORDER BY resultset in the second level query wich become a subquery.
The single row calculation in the subquery is done by mean of a WHERE criteria on the maximum of a single value calculated from the columns values on which ORDER BY clause is used.
The combination into a single value must be valid in preserving the correct ordering. I'll leave in pseudo-code as:
'<combination of count and diff>'
For example, using combination of the two values into a string type, we could have:
CONCAT(LPAD(CAST(count AS CHAR), 10, '0'), LPAD(CAST(ABS(diff) AS CHAR), 20, '0'))
The structure of the single query would be:
SELECT (Q_LVL_1.user_votes/Q_LVL_1.user_voters) as site_rating_LVL_1, Q_LVL_1.post_id as post_id_LVL_1
, Q_LVL_1.post_author as post_author_LVL_1, Q_LVL_1.post_date as post_date_LVL_1
, Q_LVL_1.category as category_LVL_1, Q_LVL_2.post_id as post_id_LVL_2
, Q_LVL_2.diff as diff_LVL_2, Q_LVL_2.site_rating as site_rating_LVL_2
, Q_LVL_2.post_author as post_author_LVL_2, Q_LVL_2.post_date as post_date_LVL_2
, Q_LVL_2.count
FROM POSTS_COMMON AS Q_LVL_1
, /* 1-row-selection query placed side by side for each Q_LVL_1's row */
(
SELECT CORE_P.post_id, CORE_P.ABS_diff as diff, P.site_rating, P.post_author, P.post_date, CORE_P.count
FROM POSTS_COMMON AS P
INNER JOIN (
SELECT FIRST(CORE_P.post_id) as post_id, ABS(CORE_P.diff) as ABS_diff, CORE_P.count
FROM (
/*
selection of posts with post_id(s) different from first level query,
not already taken and with the topmost value of
'<combination of count and diff>'
*/
) AS CORE_P
GROUP BY CORE_P.count, ABS(CORE_P.diff)
/* the one row selector */
) AS CORE_ONE_LINER ON P.post_id = CORE_ONE_LINER.post_id
) AS Q_LVL_2
ORDER BY RAND()
LIMIT 20
CORE_P selection could have more post_id(s) corresponding to the topmost value '<combination of count and diff>', so the use of GROUP BY and FIRST clauses to reach the single row.
This brings to a possible final implementation:
SELECT (Q_LVL_1.user_votes/Q_LVL_1.user_voters) as site_rating_LVL_1, Q_LVL_1.post_id as post_id_LVL_1
, Q_LVL_1.post_author as post_author_LVL_1, Q_LVL_1.post_date as post_date_LVL_1
, Q_LVL_1.category as category_LVL_1, Q_LVL_2.post_id as post_id_LVL_2
, Q_LVL_2.diff as diff_LVL_2, Q_LVL_2.site_rating as site_rating_LVL_2
, Q_LVL_2.post_author as post_author_LVL_2, Q_LVL_2.post_date as post_date_LVL_2
, Q_LVL_2.count
FROM POSTS_COMMON AS Q_LVL_1
, (
SELECT CORE_P.post_id, CORE_P.ABS_diff as diff, P.site_rating, P.post_author, P.post_date, CORE_P.count
FROM POSTS_COMMON AS P
INNER JOIN
(
SELECT FIRST(CORE_P.post_id) as post_id, ABS(CORE_P.diff) as ABS_diff, CORE_F.count
FROM (
SELECT CORE_RATING.post_id as post_id, ABS(CORE_RATING.diff) as ABS_diff, CORE_F.count
FROM (
SELECT post_id_B as post_id, site_rating_A - site_rating_B as diff
FROM POSTS_RATING_DIFFS
WHERE POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id
) as CORE_RATING
LEFT JOIN (
SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count
FROM `verus`
WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as CORE_F ON (CORE_RATING.post_id = CORE_F.post_id_winner OR CORE_RATING.post_id = CORE_F.post_id_loser)
WHERE
POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id
AND '<combination of CORE_F.count and CORE_RATING.diff>'
= MAX (
SELECT '<combination of CORE_F_2.count and CORE_RATING_2.diff>'
FROM (
SELECT site_rating_A - site_rating_B as diff
FROM POSTS_RATING_DIFFS
WHERE POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id
) as CORE_RATING_2
LEFT JOIN (
SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count
FROM `verus`
WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as CORE_F_2 ON (CORE_RATING_2.post_id = CORE_F_2.post_id_winner OR CORE_RATING_2.post_id = CORE_F_2.post_id_loser)
) /* END MAX */
) AS CORE_P
GROUP BY CORE_P.count, ABS(CORE_P.diff)
) AS CORE_ONE_LINER ON P.post_id = CORE_ONE_LINER.post_id
) AS Q_LVL_2
ORDER BY RAND()
LIMIT 20

Order by total points per user_id descending

select
((select
COALESCE(sum(b.points_received), 0) as badge_total_points
from
user_badges ub
join
badges b ON ub.badge_id = b.badge_id
where
ub.user_id = '$user_id') + (select
COALESCE(sum(aps.given_points), 0) as total_action_points
from
user_action_points uap
join
action_point_system aps ON uap.point_id = aps.point_id
where
uap.user_id = '$user_id')) as total_contribution_points
how do I retrieve a list getting the total points grouped by a user_id with this SQL statement? Anybody have suggestions?
EDIT:
select
ub.user_id,
COALESCE(sum(b.isGold), 0) as gold_count,
COALESCE(sum(b.isSilver), 0) as silver_count,
COALESCE(sum(b.isBronze), 0) as bronze_count
from
user_badges ub
join
badges b ON ub.badge_id = b.badge_id
group by ub.user_id
how can I add this query to the result of the first question?
Although there are ways to do what you want, you can build on your existing query using correlated subqueries:
select u.*,
((select COALESCE(sum(b.points_received), 0) as badge_total_points
from user_badges ub join
badges b
ON ub.badge_id = b.badge_id
where ub.user_id = u.user_id
) +
(select COALESCE(sum(aps.given_points), 0) as total_action_points
from user_action_points uap join
action_point_system aps
ON uap.point_id = aps.point_id
where uap.user_id = u.user_id
)
) as total_contribution_points
from users u
order by total_contribution_points desc;

Mysql max date within a subquery

i cant work out how to get this subquery working to get the latest date for the row.
SELECT Thread_Heading.*, Thread_Articles.*, Thread_ArticlesPost.*
FROM Thread_Heading
LEFT JOIN Thread_Articles
ON Thread_Articles.Thread_Article_Head_id=Thread_Heading.Thread_Head_id
LEFT JOIN
(
SELECT Thread_ArticlesPost.*
FROM Thread_ArticlesPost
ORDER BY Thread_ArticlePost_DT DESC
) Thread_ArticlesPost
ON Thread_ArticlesPost.Thread_ArticlePost_Article_id=Thread_Articles.Thread_Article_id
WHERE Thread_Head_Level = '5'
GROUP BY Thread_Heading.Thread_Head_id
ORDER BY Thread_ArticlePost_DT DESC
I need to order the article post date by the latest post for each Thread article.
Fairly new to sql and php i just cant work this one out any help would be appreciated.
T
ABLE: Thread_Heading |
Thread_Head_id
Thread_Head_Name
Thread_Head_Type
Thread_Head_Creator
Thread_Head_Date
Thread_Head_Level
TABLE: Thread_Articles |
Thread_Article_id
Thread_Article_Head_id
Thread_Article_Creator
Thread_Article_DT
Thread_Article_Level
Thread_Article_Type
Thread_Article_Title
TABLE: Thread_ArticlesPost |
Thread_ArticlePost_id
Thread_ArticlePost_Head_id
Thread_ArticlePost_Article_id
Thread_ArticlePost_Creator
Thread_ArticlePost_DT
Thread_ArticlePost_Level
Thread_ArticlePost_Type
Thread_ArticlePost_Title
Thread_ArticlePost_Content
I need to display the date like so:
Head Name | Article title | ORDER BY LATEST ArticlePost DT | ArticlePost Creator
The reason i used left joins was to get the left data even if there are no article or article replys.
Appreciate the help.
Have used this to display data Thanks to Blue
SELECT *
FROM
( SELECT th.Thread_Head_Name,
ta.,
tp1.maxdate,
tp2.
FROM Thread_Heading th
LEFT JOIN Thread_Articles ta
ON th.Thread_Head_id = ta.Thread_Article_Head_id
LEFT JOIN
(
SELECT max(Thread_ArticlePost_DT) maxDate,
Thread_ArticlesPost.*
FROM Thread_ArticlesPost
GROUP BY Thread_ArticlePost_Article_id
) tp1
ON tp1.Thread_ArticlePost_Article_id=ta.Thread_Article_id
LEFT JOIN Thread_ArticlesPost tp2
ON tp1.Thread_ArticlePost_Article_id = tp2.Thread_ArticlePost_Article_id
AND tp1.maxdate = tp2.Thread_ArticlePost_DT
WHERE th.Thread_Head_Level = '5'
ORDER BY tp1.maxdate DESC) m
GROUP BY Thread_Head_Name
ORDER BY Thread_ArticlePost_DT DESC
Without seeing your full table schemas you will want do something similar to this:
SELECT th.*, ta.*, tp.*
FROM Thread_Heading th
LEFT JOIN Thread_Articles ta
ON th.Thread_Head_id = ta.Thread_Article_Head_id
LEFT JOIN
(
SELECT max(Thread_ArticlePost_DT) maxDate, Thread_ArticlesPost.*
FROM Thread_ArticlesPost
GROUP BY Thread_ArticlePost_Article_id
) Thread_ArticlesPost tp
ON tp.Thread_ArticlePost_Article_id=ta.Thread_Article_id
WHERE Thread_Head_Level = '5'
GROUP BY th.Thread_Head_id
ORDER BY tp.maxdate DESC
Based on your edit the following should return the data you want:
SELECT th.Thread_Head_Name,
ta.Thread_Article_Title,
tp1.maxdate,
tp2.Thread_ArticlePost_Creator
FROM Thread_Heading th
LEFT JOIN Thread_Articles ta
ON th.Thread_Head_id = ta.Thread_Article_Head_id
LEFT JOIN
(
SELECT max(Thread_ArticlePost_DT) maxDate,
Thread_ArticlesPost.Thread_ArticlePost_Article_id
FROM Thread_ArticlesPost
GROUP BY Thread_ArticlePost_Article_id
) tp1
ON tp1.Thread_ArticlePost_Article_id=ta.Thread_Article_id
LEFT JOIN Thread_ArticlesPost tp2
ON tp1.Thread_ArticlePost_Article_id = tp2.Thread_ArticlePost_Article_id
AND tp1.maxdate = tp2.Thread_ArticlePost_DT
WHERE th.Thread_Head_Level = '5'
ORDER BY tp1.maxdate DESC
Edit #2, based on your comments, I think the below query should resolve any remaining issues:
SELECT th.Thread_Head_id,
th.Thread_Head_Name,
ta.Thread_Article_Title,
tp.Thread_ArticlePost_Creator,
tap.MaxPostDate
FROM Thread_Heading th
LEFT JOIN
(
SELECT max(ta.Thread_Article_DT) MaxArticleDate,
ta.Thread_Article_Head_id,
max(tp.Thread_ArticlePost_DT) MaxPostDate
FROM Thread_Articles ta
LEFT JOIN Thread_ArticlesPost tp
ON ta.Thread_Article_id = tp.Thread_ArticlePost_Article_id
GROUP BY Thread_Article_Head_id
) tap
ON th.Thread_Head_id = tap.Thread_Article_Head_id
LEFT JOIN Thread_Articles ta
ON tap.Thread_Article_Head_id = ta.Thread_Article_Head_id
AND tap.MaxArticleDate = ta.Thread_Article_DT
LEFT JOIN Thread_ArticlesPost tp
ON tap.MaxPostDate = tp.Thread_ArticlePost_DT
WHERE th.Thread_Head_Level = '5'
ORDER BY MaxPostDate desc
See SQL Fiddle With Demo
You don't have to have a GROUP BY clause outside side your post are already grouped on the subquery based on your latest post. Try this one,
SELECT a.*, b.*, c.*
FROM Thread_Heading a
LEFT JOIN Thread_Articles b
ON b.Thread_Article_Head_id = a.Thread_Head_id
LEFT JOIN Thread_ArticlesPost c
ON c.Thread_ArticlePost_Article_id = b.Thread_Article_id
LEFT JOIN
(
SELECT Thread_ArticlePost_Article_id, MAX(Thread_ArticlePost_DT) maxDate
FROM Thread_ArticlesPost
GROUP BY Thread_ArticlePost_Article_id
) d ON d.Thread_ArticlePost_Article_id = b.Thread_Article_id AND
c.Thread_ArticlePost_DT = d.maxDate
WHERE Thread_Head_Level = '5'
-- GROUP BY a.Thread_Head_id
ORDER BY Thread_ArticlePost_DT DESC