Solved

constructing a query with group by

Posted on 2007-11-20
13
221 Views
Last Modified: 2010-08-05
I'm having problems constructing a query that returns the desired results.

I'm working with PHPBB2 incidentally.

$sql = 'SELECT
 u.user_id,
 u.username,
 count(u.user_id) as post_count
FROM
 '.USERS_TABLE.' as u,
 '.POSTS_TABLE.' as p
WHERE
 u.user_id = p.poster_id AND
 p.post_time > '.(time()-(7*24*3600)).' AND
 u.user_id <> '.ANONYMOUS.'
GROUP BY
 u.user_id, u.username
ORDER BY
 post_count DESC';

$sql = 'SELECT
 u.user_id,
 u.username,
 count(u.user_id) as topic_count
FROM
 '.USERS_TABLE.' as u,
 '.TOPICS_TABLE.' as t
WHERE
 u.user_id = t.topic_poster AND
 t.topic_time > '.(time()-(7*24*3600)).' AND
 u.user_id <> '.ANONYMOUS.'
GROUP BY
 u.user_id, u.username
ORDER BY
 topic_count DESC';

I'm basically trying to combine the above two queries. I can get them to work individually, but fail when I try to combine them.

It's should be fairly self explanatory, but I'm trying to select the post and topic counts for users in the past week, ultimately to be ordered by 'post_count DESC, topic_count DESC'. i.e. username | # of posts made | # of topics created

Could someone kindly shed some light as to how I'd go about doing this...
0
Comment
Question by:calcanus
  • 5
  • 4
  • 4
13 Comments
 
LVL 17

Expert Comment

by:HuyBD
Comment Utility
try this


$sql = '(SELECT

 u.user_id,

 u.username,

 count(u.user_id) as post_count

FROM

 '.USERS_TABLE.' as u,

 '.POSTS_TABLE.' as p

WHERE

 u.user_id = p.poster_id AND

 p.post_time > '.(time()-(7*24*3600)).' AND

 u.user_id <> '.ANONYMOUS.'

GROUP BY

 u.user_id, u.username

ORDER BY

 post_count DESC)';

$sql.=' UNION ALL '

$sql.='(SELECT

 u.user_id,

 u.username,

 count(u.user_id) as topic_count

FROM

 '.USERS_TABLE.' as u,

 '.TOPICS_TABLE.' as t

WHERE

 u.user_id = t.topic_poster AND

 t.topic_time > '.(time()-(7*24*3600)).' AND

 u.user_id <> '.ANONYMOUS.'

GROUP BY

 u.user_id, u.username

ORDER BY

 topic_count DESC)';

Open in new window

0
 
LVL 25

Expert Comment

by:imitchie
Comment Utility
hope this satisfies your requirement
$sql = 'SELECT

 u.user_id,

 u.username,

 count(u.user_id) as post_count,

 count(u.user_id) as topic_count

FROM

 '.USERS_TABLE.' as u

 LEFT JOIN '.POSTS_TABLE.' as p ON u.user_id = p.poster_id AND

   p.post_time > '.(time()-(7*24*3600)).'

 LEFT JOIN '.TOPICS_TABLE.' as t ON u.user_id = t.topic_poster AND

   t.topic_time > '.(time()-(7*24*3600)).'

WHERE

 u.user_id <> '.ANONYMOUS.'

GROUP BY

 u.user_id, u.username

ORDER BY

 post_count DESC, topic_count DESC';

Open in new window

0
 

Author Comment

by:calcanus
Comment Utility
HuyBD,

That works but both results; post_count and topic_count are returned separately:

user_id  |  username  |  post_count
2  |  user1 |  9
3  |  user2  |  2
4  |  user3  |  3
2  |  user1  |  5
3  |  user2  |  1
4  |  user3  |  1

Is there anyway to get the results as follows:

user_id  |  username  |  post_count | topic_count
2  |  user1 |  9  | 5
3  |  user2  |  2 | 1
4  |  user3  |  3 | 1

?

@imitchie: The wrong results are returned with that query I'm afraid, which is the exact problem I encountered with everything I tried.

user_id | username | post_count | topic_count
2 | user1 | 45 | 45
4 | user3  | 3 | 3
3 | user2  | 2 | 2
0
 
LVL 17

Expert Comment

by:HuyBD
Comment Utility
you may try

HuyBD
$sql = '(SELECT

 u.user_id,

 u.username,

 count(u.user_id) as post_count

FROM

 '.USERS_TABLE.' as u,

 '.POSTS_TABLE.' as p

WHERE

 u.user_id = p.poster_id AND

 p.post_time > '.(time()-(7*24*3600)).' AND

 u.user_id <> '.ANONYMOUS.'

GROUP BY

 u.user_id, u.username

ORDER BY

 post_count DESC)';

$sql.=' UNION '

$sql.='(SELECT

 u.user_id,

 u.username,

 count(u.user_id) as topic_count

FROM

 '.USERS_TABLE.' as u,

 '.TOPICS_TABLE.' as t

WHERE

 u.user_id = t.topic_poster AND

 t.topic_time > '.(time()-(7*24*3600)).' AND

 u.user_id <> '.ANONYMOUS.'

GROUP BY

 u.user_id, u.username

ORDER BY

 topic_count DESC)';

Open in new window

0
 
LVL 17

Expert Comment

by:HuyBD
Comment Utility
or
$sql = 'SELECT * FROM (SELECT

 u.user_id,

 u.username,

 count(u.user_id) as column_count

FROM

 '.USERS_TABLE.' as u,

 '.POSTS_TABLE.' as p

WHERE

 u.user_id = p.poster_id AND

 p.post_time > '.(time()-(7*24*3600)).' AND

 u.user_id <> '.ANONYMOUS.'

GROUP BY

 u.user_id, u.username)';

$sql.=' UNION ALL '

$sql.='(SELECT

 u.user_id,

 u.username,

 count(u.user_id) as column_count

FROM

 '.USERS_TABLE.' as u,

 '.TOPICS_TABLE.' as t

WHERE

 u.user_id = t.topic_poster AND

 t.topic_time > '.(time()-(7*24*3600)).' AND

 u.user_id <> '.ANONYMOUS.'

GROUP BY

 u.user_id, u.username) as T

ORDER BY

 column_count DESC'; 

Open in new window

0
 
LVL 17

Expert Comment

by:HuyBD
Comment Utility
sorry, I have missing!
$sql = 'SELECT user_id,username,count(post_count) as post_count,

count(topic_count) as topic_count FROM (SELECT

 u.user_id,

 u.username,

 count(u.user_id) as post_count,

 0 as topic_count

FROM

 '.USERS_TABLE.' as u,

 '.POSTS_TABLE.' as p

WHERE

 u.user_id = p.poster_id AND

 p.post_time > '.(time()-(7*24*3600)).' AND

 u.user_id <> '.ANONYMOUS.')';

$sql.=' UNION ALL '

$sql.='(SELECT

 u.user_id,

 u.username,

 0 as post_count,

 count(u.user_id) as topic_count

FROM

 '.USERS_TABLE.' as u,

 '.TOPICS_TABLE.' as t

WHERE

 u.user_id = t.topic_poster AND

 t.topic_time > '.(time()-(7*24*3600)).' AND

 u.user_id <> '.ANONYMOUS.') as T

GROUP BY

user_id, username

ORDER BY

 column_count DESC'; 

Open in new window

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 25

Expert Comment

by:imitchie
Comment Utility
sorry, was counting the user_id. just replace with counting something from the post and topics tables, as follows
$sql = 'SELECT

 u.user_id,

 u.username,

 count(p.poster_id) as post_count,

 count(t.topic_poster) as topic_count

FROM

 '.USERS_TABLE.' as u

 LEFT JOIN '.POSTS_TABLE.' as p ON u.user_id = p.poster_id AND

   p.post_time > '.(time()-(7*24*3600)).'

 LEFT JOIN '.TOPICS_TABLE.' as t ON u.user_id = t.topic_poster AND

   t.topic_time > '.(time()-(7*24*3600)).'

WHERE

 u.user_id <> '.ANONYMOUS.'

GROUP BY

 u.user_id, u.username

ORDER BY

 post_count DESC, topic_count DESC';

Open in new window

0
 

Author Comment

by:calcanus
Comment Utility
@imitchie: That still returns the same results.

 It's seems as though the post count is getting multiplied by the topic count.

2 | user1 | 45 | 45
4 | user3  | 3 | 3
3 | user2  | 2 | 2

This is what it should be:

2  |  user1 |  9  | 5
3  |  user2  |  2 | 1
4  |  user3  |  3 | 1

@HuyBD:

There's a query in there some where. I can't figure out where, that query is a little beyond my ability.
0
 

Author Comment

by:calcanus
Comment Utility
Sorry, I mean an error.
0
 
LVL 25

Expert Comment

by:imitchie
Comment Utility
i see the error of my ways leading you up the rosy garden path. please try this
 count(distinct p.poster_id) as post_count,

 count(distinct t.topic_poster) as topic_count

Open in new window

0
 

Author Comment

by:calcanus
Comment Utility
The results remain incorrect I'm afraid.

2  |  user1 | 1 | 1
3  |  user2  | 1 | 1
4  |  user3  | 1 | 1

All post and topic counts return as 1.
0
 
LVL 25

Accepted Solution

by:
imitchie earned 250 total points
Comment Utility
okay, assuming posts by the same user will always have distinct post_time, and topic_time will always be distinct...

 count(distinct p.post_time) as post_count,
 count(distinct t.topic_time) as topic_count

will now do it. just in case, I'm getting phpbb2 resurrected on my test server in case i need to actually test my next suggestion
0
 

Author Comment

by:calcanus
Comment Utility
ah ha! The query now returns the correct result.

I was a bit worried about the possibility of two topics or posts being posted at exactly the same time, so I substituted p.post_time and t.topic_time for p.post_id and  t.topic_id , i.e.

count(DISTINCT p.post_id) AS post_count,
count(DISTINCT t.topic_id) AS topic_count

and the results remain correct.

Thanks for your help!
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Creating and Managing Databases with phpMyAdmin in cPanel.
Load balancing is the method of dividing the total amount of work performed by one computer between two or more computers. Its aim is to get more work done in the same amount of time, ensuring that all the users get served faster.
Video by: Steve
Using examples as well as descriptions, step through each of the common simple join types, explaining differences in syntax, differences in expected outputs and showing how the queries run along with the actual outputs based upon a simple set of dem…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now