Get last record of each record group - php

I don't know how to write the SQL syntax of getting the last record (according to recent post and is not replied to).
My table
+-------------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-----------------------+------+-----+---------+----------------+
| notification_id | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |
| user_id | mediumint(8) unsigned | NO | | NULL | |
| notification_msg | text | NO | | NULL | |
| notification_date | int(11) unsigned | NO | | NULL | |
| private_message | tinyint(1) unsigned | NO | | 0 | |
| has_replied | tinyint(1) unsigned | NO | | 0 | |
| reply_id | mediumint(8) unsigned | NO | | 0 | |
+-------------------+-----------------------+------+-----+---------+----------------+
Basically for each threaded notification, it should get the last record of each notification record and check if has_replied is 0, if it is 0 then it should return it so PHP can read whether there is a notification that hasn't been replied to. So like, it should return like this (pseudo):
+--------------+-----+-----+
| username | 1 | 4 |
| username2 | 0 | 2 |
+--------------+-----+-----+
Where the second column represents if the last post has been replied to or not.
My current SQL syntax (works but does not get the last record and if it's replied to):
SELECT n.*,
m.user_id,
m.username
FROM notifications n
INNER JOIN members m ON n.user_id = m.user_id
WHERE private_message = 1
AND reply_id = 0
ORDER BY has_replied ASC,
notification_date DESC

Select m.user_id, m.username
, N...
From members As M
Join (
Select user_id, Max( notification_id ) As notification_id
From notifications
Group By user_id
) As UserLastNotification
On UserLastNotification.user_id = m.user_id
Join notifications As N
On N.notification_id = UserLastNotification.notification_id
Where N.private_message = 1
And N.reply_id = 0
Order By N.has_replied, N.notification_date Desc
Note that this will filter on each user's last notification being a private message and having a reply_id being zero.

A simple
LIMIT 1
at the end of the query should be sufficient to only return the last post.

Related

MySQL Query - select all comments for a post

I have these tables:
tbl_posts:
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| date | varchar(10) | NO | | NULL | |
| content | text | NO | | NULL | |
| status | tinyint(1) | NO | | NULL | |
| person_id | int(10) | NO | | NULL | |
+---------------+------------------+------+-----+---------+----------------+
tbl_comments:
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| comment | varchar(10) | NO | | NULL | |
| post_id | int(10) | NO | | NULL | |
| person_id | int(10) | NO | | NULL | |
+---------------+------------------+------+-----+---------+----------------+
and tbl_person which has person_id and some other fields...
i want to select all posts posted by a certain person and all comments for each of those posts (just like facebook)
i tried this query but it just bring me one comment for each post
select * from tbl_posts right join tbl_comments on tbl_posts.id = tbl_comments.post_id join tbl_person on tbl_person.id = tbl_posts.Person_id and tbl_comments.Person_id = 3 group by tbl_comments.id
If your foreign keys are set up correctly, an inner join should be fine. And, you don't need the group by:
select *
from tbl_posts join
tbl_comments
on tbl_posts.id = tbl_comments.post_id join
tbl_person
on tbl_comments.Person_id = 3;
Actually, I suspect the problem is tbl_person.id = tbl_posts.Person_id. Your query was returning only people who commented on their own posts.
When joining tables, you should always make sure there is a relationship between the tables you wish to join. In your case, this should give you all posts posted by a certain person and all comments for each of those posts:
SELECT *
FROM tbl_posts
LEFT JOIN
tbl_comments ON tbl_posts.id = tbl_comments.post_id
LEFT JOIN tbl_person ON tbl_comments.Person_id = tbl_person.id;
So instead of doing
tbl_comments.Person_id = 3
You need to JOIN the tbl_comments and tbl_person tables like so:
tbl_comments.Person_id = tbl_person.id

Get profile posts from friends

I'm making a small CMS, where you can have friends, and post on their walls. I'm making a page where you can view all the posts your friends have posted (on their profiles) however, I cannot get it to properly function.
Table: friends
+---------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+---------+------+-----+---------+----------------+
| friend_id | int(10) | NO | PRI | NULL | auto_increment |
| user1_id | int(10) | NO | | NULL | |
| user2_id | int(10) | NO | | NULL | |
| friends_since | int(10) | NO | | NULL | |
+---------------+---------+------+-----+---------+----------------+
Table: profile_posts
+----------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------+------+-----+---------+----------------+
| post_id | int(12) | NO | PRI | NULL | auto_increment |
| posted_user_id | int(12) | YES | | NULL | |
| user_id | int(12) | YES | | NULL | |
| date_posted | int(11) | YES | | NULL | |
| total_likes | int(12) | YES | | NULL | |
| users_liked | text | YES | | NULL | |
| total_dislikes | int(12) | YES | | NULL | |
| users_dislikes | text | YES | | NULL | |
| message | text | YES | | NULL | |
+----------------+---------+------+-----+---------+----------------+
Basically, if I want to determine if a user has posted on their profile as a status, the posted_user_id and user_id columns in the table profile_posts have to match (posted_user_id is the user's id of the post being posted on, and user_id is the user_id is the id of the person who posted that message).
However, I've tried multiple times to get friend's statuses.
SELECT *
FROM `friends` AS `f`
LEFT JOIN `profile_posts` AS `pp`
ON `pp`.posted_user_id = `pp`.user_id
WHERE
`f`.user1_id != 2 OR
`f`.user2_id != 2
ORDER BY `pp`.`date_posted` DESC
LIMIT 0,15;
(Hurray for not working! :D)
SELECT `f`.*,`pp`.*,
IF(`f`.user1_id=2, `f`.user2_id, `f`.user1_id) AS `uid`
FROM `friends` AS `f`
LEFT JOIN `profile_posts` AS `pp`
ON `pp`.posted_user_id =`uid`
WHERE
`f`.user1_id = `uid` OR
`f`.user2_id = `uid`
ORDER BY `pp`.`date_posted` DESC
LIMIT 0,15;
I'm not sure how to do this honestly, It's starting to make me rage as I cannot figure how to do this. :/
Never mind, figured out how to do it. :D
EDIT:
SELECT
`f`.*,
`pp`.*,
`ai`.`name`,
`ai`.`lastname`
FROM `friends` AS `f`
LEFT JOIN `profile_posts` AS `pp`
ON
`pp`.`posted_user_id` = `pp`.`user_id` AND
`pp`.`user_id` = `f`.user1_id OR
`pp`.`user_id` = `f`.user2_id
LEFT JOIN `account_info` AS `ai`
ON `ai`.`u_id` = `pp`.`user_id`
WHERE
`pp`.`user_id` = `pp`.`posted_user_id` AND
`f`.user1_id = 1 OR
`f`.user2_id = 1 AND
`pp`.`user_id` = `pp`.`posted_user_id`
GROUP BY `pp`.post_id
ORDER BY `pp`.date_posted DESC
LIMIT 0,20;
Selects the current user's friends, then it grabs all profile posts of their friends and then joins the account information table to get the name, and other information.
I'm trying to see if I can make this smaller, if not better..

Mysql one to many relationship. Order by number of rows in second table

I have created a voting system in php and mysql. When a user votes on an id, a record is inserted in "votes" referencing the FK media_id. When I then display the entries I use this query to get the number of votes for each entry:
$sql = "SELECT COUNT(*) FROM insta_votes WHERE media_id ='".$mediaid."'";
if ($res = $db->query($sql)) {
return $res->fetchColumn();
}
return 0;
This works fine, but I want to be able to sort the results by the number of votes they have. Preferably using just one query. How can I achieve this?
The tables are structured like this:
votes table
+-----------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| media_id | varchar(255) | NO | | NULL | |
| ip | varchar(20) | NO | | NULL | |
| c_time | timestamp | NO | | CURRENT_TIMESTAMP | |
| sessionid | varchar(30) | NO | | NULL | |
+-----------+--------------+------+-----+-------------------+----------------+
entries table
+---------------+--------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+-------------------+-------+
| page_id | int(11) | NO | MUL | NULL | |
| media_id | varchar(255) | NO | PRI | NULL | |
| url | varchar(255) | NO | | NULL | |
| c_time | datetime | NO | | NULL | |
| likes | int(11) | YES | | NULL | |
| deleted | tinyint(1) | NO | | 0 | |
| inserted_time | timestamp | YES | | CURRENT_TIMESTAMP | |
| numReports | int(11) | NO | | 0 | |
+---------------+--------------+------+-----+-------------------+-------+
Thank you!
If I understand the tables correctly (and I may not), each entries row may reference multiple votes rows. In that case, the query you need will go something like this:
SELECT
entries.page_id,
COUNT(*) AS VoteCount
FROM entries
INNER JOIN votes ON entries.media_id = votes.media_id
GROUP BY entries.page_id
ORDER BY VoteCount
If you add additional entries columns to the SELECT list, be sure to add them to the GROUP BY list as well.
Addendum: #JuanPabloCalifano pointed out, correctly, that this query won't include entries with zero votes. Here's how to include them:
SELECT
entries.page_id,
COALESCE(COUNT(votes.id), 0) AS VoteCount
FROM entries
LEFT JOIN votes ON entries.media_id = votes.media_id
GROUP BY entries.page_id
ORDER BY VoteCount
SELECT COUNT(*) as CNT, `media_id` FROM `insta_votes` GROUP BY `media_id` order by 1;
SELECT COUNT(*), media_id FROM insta_votes
GROUP BY media_id
ORDER BY COUNT(*);"

MySQL select statement giving error

This is the MySQL select statement I have that's giving me the error - Unknown column 'Regattas.regatta_id' in 'on clause'
SELECT
Regattas.regatta_id,
Events.event_id,
Events.event_name
FROM Regattas, Events
LEFT JOIN Regatta_Events AS Regatta_Events_1 ON Regatta_Events_1.fk_event_id = Events.event_id
LEFT JOIN Regatta_Events AS Regatta_Events_2 ON Regatta_Events_2.fk_regatta_id = Regattas.regatta_id
WHERE Regattas.regatta_id = {$regattaId}
The layout of the tables are like the below:
Regattas Table:
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| regatta_id | int(11) | NO | PRI | NULL | auto_increment |
| regatta_name | varchar(100) | NO | | NULL | |
| regatta_start_date | date | NO | | NULL | |
| regatta_end_date | date | NO | | NULL | |
| regatta_start_time | time | NO | | NULL | |
| regatta_venue_id | int(11) | NO | | 0 | |
+--------------------+--------------+------+-----+---------+----------------+
Events Table:
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| event_id | int(11) | NO | PRI | NULL | auto_increment |
| event_name | varchar(255) | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
And the Regatta_Events table like this - Conjunction table:
+-------------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------+------+-----+---------+----------------+
| regatta_events_id | int(11) | NO | PRI | NULL | auto_increment |
| fk_regatta_id | int(11) | NO | | 0 | |
| fk_event_id | int(11) | NO | | 0 | |
+-------------------+---------+------+-----+---------+----------------+
Please Help me fix this I have been on it for a while.
Assuming this is what you're trying to do, you can use UNION ALL for this. You don't need the OUTER JOIN with the first query -- I left it just for reference (not 100% positive what you're trying to achieve):
SELECT
Regattas.regatta_id,
NULL event_id,
NULL event_name
FROM Regattas
LEFT JOIN Regatta_Events ON Regatta_Events.fk_regatta_id = Regattas.regatta_id
WHERE Regattas.regatta_id = {$regattaId}
UNION ALL
SELECT
NULL regatta_id,
Events.event_id,
Events.event_name
FROM Events
LEFT JOIN Regatta_Events ON Regatta_Events.fk_event_id = Events.event_id
I'm not completely sure I understand your desired results. This will return all results from the Events table, and only those results from the Regattas table where the id matches in the input.
Perhaps instead you are looking for something like this:
SELECT
Regattas.regatta_id,
Events.event_id,
Events.event_name
FROM Regattas
LEFT JOIN Regatta_Events ON Regatta_Events.fk_regatta_id=Regattas.regatta_id
LEFT JOIN Events ON Regatta_Events.fk_event_id=Events.event_id
WHERE Regattas.regatta_id = {$regattaId}
I think this should be simple join to return you Regetta_id, event_ID and event_name combination.
SELECT
Regattas.regatta_id,
Events.event_id,
Events.event_name
FROM Regattas as rg
LEFT JOIN Regatta_Events as re ON re.fk_event_id = rg.regatta_id
LEFT JOIN Events AS ev ON re.fk_regatta_id = ev.event_id
WHERE rg.regatta_id = {$regattaId}

In MySQL, how to select empty records

I have the following MySQL Table Structure:
mysql> desc customers;
+---------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+-------------+------+-----+---------+-------+
| hash | varchar(32) | NO | PRI | NULL | |
| date_joined | date | NO | | NULL | |
| agent_code | int(5) | NO | UNI | | |
+---------------------+-------------+------+-----+---------+-------+
mysql> desc persons;
+--------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+-------------+------+-----+---------+-------+
| agent_code | int(5) | NO | UNI | | |
| team_id | int(2) | YES | | 0 | |
| hash | varchar(32) | NO | PRI | NULL | |
+--------------------+-------------+------+-----+---------+-------+
mysql> desc teams;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| leader | varchar(32) | NO | UNI | NULL | |
+--------+-------------+------+-----+---------+----------------+
And I'd wish to generate a report of sales by Team.
The SQL Query that I'm using is the following:
SELECT COUNT(`customers`.`agent_code) AS `customer_count`, `teams`.`name`
FROM `customers`
JOIN `persons` ON `customers`.`agent_code` = `persons`.`agent_code`
JOIN `teams` ON `persons`.`team_id` = `teams`.`id`
GROUP BY `teams`.`name`
And it shows the following information:
+----------------+--------+
| customer_count | name |
+----------------+--------+
| 3 | Team 1 |
+----------------+--------+
However I'd like to see the "customer_count" of all the teams in the database, even if the customer_count is null (or zero) for a given team. I have 15 teams in my database, so I'd like to see something like:
+----------------+--------+
| customer_count | name |
+----------------+--------+
| 3 | Team 1 |
| 0 | Team 2 |
| 0 | Team 3 |
| 0 | Team 4 |
+----------------+--------+
I have tried to execute some variants of the following Query, but I always get an error saying that the syntax of OUTER JOIN is incorrect, even though I've read the documentation, and it is correct.
SELECT COUNT( `customers`.`agent_code` ) AS `customer_count` , `teams`.`name`
FROM `customers`
LEFT JOIN `persons` ON `customers`.`agent_code` = `persons`.`agent_code`
LEFT OUTER JOIN `teams` ON `persons`.`team_id` = `teams`.`id`
GROUP BY `teams`.`name`
How can I alter my current query in order to display such result?
You have mistake get main table is person - I suggest your main table is team
SELECT COUNT(`customers`.`id`) AS `customer_count` , `teams`.`name`
FROM `teams`
JOIN `persons` ON `persons`.`team_id` = `teams`.`id`
LEFT JOIN `customers` ON `customers`.`agent_code` = `persons`.`agent_code`
GROUP BY `teams`.`name`
Update: if you do have empty teams, than you need to set left join on persons
SELECT COUNT(`customers`.`id`) AS `customer_count` , `teams`.`name`
FROM `teams`
LEFT JOIN `persons` ON `persons`.`team_id` = `teams`.`id`
LEFT JOIN `customers` ON `customers`.`agent_code` = `persons`.`agent_code`
GROUP BY `teams`.`name`

Categories