two tables - posts and users
column posts.user is matching with users.id.
I want to count all posts from all users, this way:
user1 5
user2 3
user3 9
... and so on meaning that user1 from users has 5 instances from posts... etc.
$items = '';
$sql = "select users.name, posts.user from users inner join posts on users.id = posts.user";
$stmt = $db->query($sql);
while($row = $stmt->fetch()){
$count = $stmt->rowCount();
$items .= "<div><span class='spanuser'>" . $row['name'] . "</span> <span class='spancount'>" . $count . "</span></div>";
}
echo $items;
result
user1 74 // 74 is total number of `posts` rows
user2 74
user3 74
... all users - 74
Any help?
You need to use GROUP BY with LEFT JOIN, e.g.:
SELECT u.name, COUNT(p.id) AS `count`
FROM users u LEFT JOIN posts p ON u.id = p.user
GROUP BY u.name;
This will give you the desired output.
Update
As per our discussion, to get the count for today, you can use the following query:
SELECT u.name, COUNT(p.id) AS `count`
FROM users u LEFT JOIN posts p ON u.id = p.user
WHERE DATE(datetime) = DATE(NOW())
GROUP BY u.name;
Similarly, you can use BETWEEN operator to get the same count for a date range, e.g., for last 7 days, you can use this:
SELECT u.name, COUNT(p.id) AS `count`
FROM users u LEFT JOIN posts p ON u.id = p.user
WHERE DATE(datetime) BETWEEN DATE_ADD(NOW(), INTERVAL -7 DAY) AND DATE(NOW())
GROUP BY u.name;
Also, you need to update the php to use the count returned by the query and not rowCount, e.g.:
$items .= "<div><span class='spanuser'>" . $row['name'] . "</span> <span class='spancount'>" . $row['count'] . "</span></div>";
Try doing it this way using Count()
$items = '';
$sql = "SELECT u.name,COUNT(p.user) as pCount FROM users u INNER JOIN posts p on u.id = p.user GROUP BY u.name";
$stmt = $db->query($sql);
while($row = $stmt->fetch()){
$items .= "<div><span class='spanuser'>" . $row['name'] . "</span> <span class='spancount'>" . $row['pCount'] . "</span></div>";
}
echo $items;
Try use COUNT(). To count the posts.user
https://www.w3schools.com/sql/sql_count_avg_sum.asp
You want to group by the user and count the number of posts, to get the final total row you want a WITH ROLLUP e.g.
SELECT COALESCE(User,'TOTAL') AS Name,
Count(Post.ID) AS CountOfPosts
FROM Users
LEFT JOIN Posts ON Posts.USer= Users.id
GROUP BY Users.id WITH ROLLUP
The "total" row will actually have a value of null so we use the COALESCE to change null into TOTAL
Related
I'm trying to fetch information from 2 different MySQL tables.
The primary table is this one:
From this one I use the information to get the average rate from this:
How can I write an SQL query that will get me the average rating by counting all the rows with rating_house = house_id, and sort it by highest rating and if equal ratings, the one with the most rates.
This is what I have come up with myself:
$sql = "SELECT l.location_address, "
. "r.rating_structure+r.rating_inventory+r.rating_service/3 AS average "
. "FROM houses h "
. "LEFT JOIN rating r ON h.house_id = r.rating_house "
. "LEFT JOIN location l ON h.house_address = l.location_id "
. "WHERE h.house_deleted IS NULL SORT BY average DESC LIMIT 10";
$result = $db_connect->prepare($sql);
if($result->execute()){
while($user_data = $result->fetch(PDO::FETCH_ASSOC)){
$user_data['location_address']."<br>";
}
}
However I get no output?
For performance use INNER JOINs instead of LEFT JOINs if you know that the related rows must exist.
SELECT l.location_address,
(SUM(r.rating_structure)+SUM(r.rating_inventory)+SUM(r.rating_service))/3 AS average
FROM houses h
INNER JOIN rating r ON h.house_id = r.rating_house
INNER JOIN location l ON h.house_address = l.location_id
WHERE h.house_deleted IS NULL
GROUP BY l.location_address
ORDER BY 2,
(SUM(r.rating_structure)+SUM(r.rating_inventory)+SUM(r.rating_service)) DESC
LIMIT 10
Below query should return houses sorted by average ratings:
select h.house_id, (sum(hr.rating_structure) + sum(rating_inventory) + sum(rating_service))/3 as "average"
from house h left outer join house_rating hr on h.house_id = hr.rating_house
group by h.house_id
order by average
i need select some data from two tables ,
please help me use inner join for this selection .
players in selction2 must not be in selection1...
first select :
$rs = "SELECT *
FROM `player`
WHERE `status`=1 AND `credit`>=1 AND `username` NOT LIKE '$user'
ORDER BY ls ASC,credit DESC
LIMIT 0 ,10;
Second: this players must remove from result of selection1
$rs2 = "SELECT *
FROM `ip_log`
WHERE `playerid`='$ui' AND `win`='1' AND `date`='$date' ";`
You can use LEFT JOIN for this:
This shows the log messages for everyone not in selection 1.
SELECT l.*
FROM ip_log AS l
LEFT JOIN
(SELECT username
FROM player
WHERE status = 1 AND credit >= 1 AND username NOT LIKE '$user'
ORDER BY ls ASC, credit DESC
LIMIT 10) AS p
ON l.player = p.username
WHERE win = 1 and date = '$date'
AND p.username IS NULL
This shows the top 10 player data, except the ones with log messages in selection 2
SELECT p.*
FROM player AS p
LEFT JOIN ip_log AS l ON l.player = p.username AND l.win = 1 AND l.date = '$date'
WHERE p.status = 1 AND p.credit >= 1 AND p.username NOT LIKE '$user'
AND l.player IS NULL
ORDER BY p.ls ASC, p.credit DESC
LIMIT 10
In both cases, testing a column in the second table with IS NULL makes it return only the rows in the first table that don't have a match in the second table. See
Return row only if value doesn't exist
You can do it with LEFT JOIN
SELECT player.*,ip_log.* FROM `player` LEFT JOIN `ip_log` ON player.id!=ip_log.playerid GROUP BY player.id
I have a 4 table merge going on and in the end I want it to be sorted by an "ORDER BY" according to some variable. Right now this is always returning the same order of entries.
Something like:
if(isset($_GET['filter'])){
$filter = $_GET['filter'];
#Example $filter = 'date' or team or game_num
$q = $db->prepare("SELECT g.game_num, s.date, t.team
FROM schedule n
LEFT JOIN g_lkp g
ON n.game_num = g.game_num
LEFT JOIN dates s
ON n.date = s.date
LEFT JOIN teams t
ON n.home_team_nbr = t.team
ORDER BY '$filter' ");
$q->execute();
$qR = $q->fetchAll(PDO::FETCH_ASSOC);
if ($q->rowCount() > 0) {
foreach ($qR as $row) {
echo '
//First check value of $filter
$q = $db->prepare("SELECT g.game_num game_num, s.date date, t.team team
FROM schedule n
LEFT JOIN g_lkp g
ON n.game_num = g.game_num
LEFT JOIN dates s
ON n.date = s.date
LEFT JOIN teams t
ON n.home_team_nbr = t.team
ORDER BY $filter ");
I have three tables underlying a blog: one for users, one for comments and one for threads.
Not all the records retrieved are echoed by PHP and I think it may be to do with NULL values, for example on my memberlist page the following query retrieves data on four users:
SELECT COUNT(Topics.MemberID) AS NumberOfTopics, Users.id,
Users.FirstName, Users.LastName, Users.Joined
FROM Users LEFT JOIN Topics ON Users.id=Topics.MemberID GROUP BY Topics.MemberID
However if the last user(s) at the end of the list has no topics (NumberOfTopics = 0) they are not presented.
If a user has a post count of 0 but they following record has a post count that isn't 0 the user is shown. Why?
Here is the complete code:
$result = mysql_query("SELECT COUNT(Topics.MemberID) AS NumberOfTopics, ".
"Users.id, Users.FirstName, Users.LastName, Users.Joined ".
"FROM Users LEFT JOIN Topics ON Users.id=Topics.MemberID ".
"GROUP BY Topics.MemberID")
or die("Query failed with error: ".mysql_error());
echo "<table border='1'>
<tr>
<th>Name</th>
<th>Joined</th>
<th>No. of posts</th>
</tr>";
while($row = mysql_fetch_assoc($result))
{
echo "<tr>";
echo "<td><a href='/neuro/profile.php?userid=$row[id]'>" .
$row['FirstName'] . " " . $row['LastName'] . "</a></td>";
echo "<td>" . $row['Joined'] . "</td>";
echo "<td>" . $row['NumberOfTopics'] . "</td>";
echo "</tr>";
}
echo "</table>";
mysql_close($con);
Thanks for reading!
I believe the problem is that your GROUP BY will force the elimination of NULLs.
I normally will use subquery in these circumstances simply because it is easier to read and understand:
SELECT (select count(*) from Topics T where T.MemberID = U.id) AS NumberOfTopics,
Users.id, Users.FirstName, Users.LastName, Users.Joined
FROM Users u
I think it's because of your group by.
Try:
select
topics.count,
users.id,
users.firstname,
users.lastname,
users.joined
from
users left join
(
select
topics.memberid,
count(*) count
from
topics
group by
topics.memberid
) topics on users.id = topics.memberid
This should gather the count of topics that you're after in a sub query and then left join those counts against all users.
Your query is somewhat contradictory. LEFT JOIN will return all rows from the left table, even if there are no matches in the right table. HOWEVER in the case of your query you are grouping your records by Topics.MemberID. For users with no post their will be no record shown!! Try the following query:
SELECT
COUNT(Topics.MemberID) AS NumberOfTopics, Users.id,
Users.FirstName, Users.LastName, Users.Joined
FROM Users LEFT JOIN Topics ON Users.id=Topics.MemberID
GROUP BY Users.id
Your query seems incorrect.
I'd use an inner join
SELECT COUNT(*) AS NumberOfTopics
, Users.id
, Users.FirstName
, Users.LastName
, Users.Joined
FROM Users
INNER JOIN Topics ON Users.id=Topics.MemberID
GROUP BY Topics.MemberID
$sSql = "SELECT COUNT(DISTINCT `tsu`.`id`) AS `count`
FROM `" . $this->_sPrefix . "users` AS `tsu`
INNER JOIN `" . $this->_sPrefix . "entries` AS `tse`
ON `tsu`.`id`=`tse`.`subscriber_id`
AND `tse`.`subscriber_type`='" . BX_DOL_SBS_TYPE_VISITOR . "'
WHERE 1
GROUP BY `tsu`.`id`
LIMIT 1";
Instead of counting the entries, it only returns 1. If I remove the group BY clause then it works. How can I fix the GROUP BY to make it work better?
The WHERE 1 does nothing, so it can be removed.
The GROUP BY can also be removed since you are not grouping by anything, your COUNT DISTINCT is on the whole table, no?
As Orbling points out, the LIMIT 1 can be removed too because COUNT DISTINCT returns only one value by definition.
Does it do what you want then?
You are grouping by tsu.id.
Each individual tsu.id group will by definition only have 1 distinct tsu.id in the group what do you expect it to return?
SELECT u.id, COUNT(e.id)
FROM users AS u
INNER JOIN entries AS e ON e.subscriber_id = u.id
WHERE e.subscriber_type = 'BX_DOL_SBS_TYPE_VISITOR'
GROUP BY u.id