Select rows from MySQL where data is not the same - php

So i have a chat system and a topbar with notifications
What i want to do is load the last message from the last X persons the user has chatted
So i dont want to spam the notifications with X number of messages from the same person but i want to load the very LAST message from X number of persons
So here is my problem (example):
Imagine if one person sent the user 8 messages and i limit the message query to 8 results. The query will return 8 messages from the same person but i've made a PHP filter that will echo only 1 message from one person. So basically this will only echo 1 message from 1 person but wont echo any other messages from any other person because ive limited the result query to 8 and this user already spammed 8 messages
This is my PHP filter (but i want to do this in SQL)
foreach ($sideMess as $smes) {
if (!isset($showedList[$smes['id']])) {
echo '<div class="mes_wrap" id="ppl_', $smes['id'] ,'">
<img src="', $smes['avatar'] ,'">
<h4>', $smes['firstname'] ,' ', $smes['lastname'] ,'</h4>
</div>';
$showedList[$smes['id']] = true;
$cS ++;
}
}

As per your specification, it seems that you want list of last message from multiple users, i.e, user-wise last message.
select * from
(select * from
messages
order by user_id,message_time desc) temp
group by user_id;

Okay, its solved!
I used GROUP BY sender_id before ORDER BY
Thanks for your help!

Related

How To Count Read and Unread message in PHP mysql

I want to make a read and Unread message count from Mysql.
This is my PHP code :
<?php
$dbdata = "SELECT * FROM users";
if ($result = mysqli_query($db, $dbdata)) {
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_array($result)) {
echo "<li class=online'><a href='?user=" .
$row['username'] .
"'><img alt='user pics' src='img/demo/av1.jpg' /> <span>" .
$row['fname'] . ' ' .
$row['lname'] . "</span><span class='msgcount'> 0</span></a></li>";
}
mysqli_free_result($result);
} else {
echo "No Students Found.";
}
} else {
echo "ERROR: Could not able to execute. ";
}
?>
I want <span class='msgcount'> 0</span> to display a count of the unread messages of that user. And if the user is already clicked, the messages unread becomes 0 because messages are shown upon click.
Can you help me solve this logic? I just want to notify that there is an unread message. Thank you masters please help me.
This is the Output image of the Chat Message:
I am new to php. So this can serve as an alternative till a better answer is tendered.
You could create a table that looks like that of your message. Then when you send a message insert the data into the two tables. Next, select your message in your normal way. And select the number of rows from your look alike table then print it in the span for unread messages. Then onclick let mysqli delete the messages from the look alike table. Autoupdate the span with jquery.
I'm assume that besided the users table, you alse have a messages table.
And I will boldly assume your messages table looks like this:
id int pk,
to_user_id int fk,
from_user_id int fk,
read bool default false,
title varcher(250),
body text,
created_at datetime,
updated_at datetime
So, users and messages have a 1:M relationship and rightfully so
You join, filter and count users and messages at every page load or at every few seconds
SELECT u.id, u.name as from, count(1) as total
FROM users AS u
JOIN messages AS m on u.id = m.from_user_id
WHERE
to_user_id = ? -- this is the authenticated user id!
AND `read` is false
GROUP BY from_user_id
This will give you tuples like so:
id, from, total
22, john, 1
124, frank, 3
523, bob, 1
11, david, 3
But this will require some more work, because this will only return the users with unread messages. So you can easily check if there are any messages by friends.
If you want just a general message count to show, for example on a banner:
SELECT count(1) FROM messages WHERE `read` is false and to_user_id = ? -- ? is the authenticated user id
Extra:
There are tons of fancier ways to go, like using redis to cache the message count.
What I've just describe is probably the simpler and uses zero auxiliar infrastructure, aka the burn mysql burn strategy.
pro tip:
if your application is going to rely heavily on messages like a slack type of app, it's not a good idea to store messages in a SQL database. But if you are just learning or tinkering, go ahead!
In your database create a column "Status" of datatype int(1) Default 0.
If I read the message update the status with 1, as by default we are using 0 that means its unread message.
Now at the time counting. Create two variables $total_read = 0 and $total_unread = 0.
Inside your while loop your can go with this
while($row = mysqli_fetch_array($result)) {
if($row['status'] == 0)
{
$total_unread = total_unread + 1
} else {
$total_read = total_read + 1
}
}

How to query SQL database from php on which user didn't send in his hour report for the last 30 days

I have an hoursheet import form where users submit the hours they worked per day. This data is send to a table called hours.
This table contains the columns:
user, day, hours, begintime, endtime
I want to send every employee an email when they didn't send in their worked hours per day.
What I've tried so far: create an array with the active users. I created an array from an sql query in php with all the hoursheets per user from 'yesterday'.
With array_diff_assoc I have the users which didn't send in their hoursheet for 'yesterday'.
So no problem here. But I'm looking for a more clean solution that can do it for several days in the past. Let's say the last month. Does anybody have a good suggestion to push me in the right direction?
Database is sql
Programming language php
Don't get me wrong, I don't need tons of code. I'm not lazy I want to try to look for this myself. I just need a push in the right direction.
Real-life example:
Table structure:
Hourimport table <----one to many <---- User table
|
one to many
|
Hourimport detail
Hourimport contains the dayreports unique record number, user, date, status, mail
Hourimport detail contains the details records of the dayreport. Multiple detail records per day.. For example one travel hour from 8 to 9 and working hours from 9 to 5. Breaks and miles driven. *not needed for this example because all the data I need is in the hourimport table.
users contains id, name, mail etc
echo '<br>STEP 1: <br>Connected successfully <br><br>';
$yesterdayT = date('Y-m-d', mktime(0, 0, 0, date("m"), date("d")-1, date("Y")));
$yesterday = date("Y-m-d H:i:s", strtotime($gisterenT));
$yesterday = "'$gisteren'";
//////////////////////////////////////////////////////////
$result = mysql_query("select id as employee from users inner join user_group on users.id=user_group.user_id where group_id=10 or group_id=11");
if (!$result) {
echo 'Could not run query: ' . mysql_error();
exit;
}
$rows = array();
while($rows[]=mysql_fetch_array($result));
echo "<br>A <--<pre>";
print_r ($rows);
echo "</pre><br><br>";
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
$result1 = mysql_query("select employee from hourimport INNER JOIN hourimport_detail ON hourimport.id=hourimport_detail.parent_id WHERE hourimport.date =$yesterday");
if (!$result1) {
echo 'Could not run query: ' . mysql_error();
exit;
}
$rows1 = array();
while($rows1[]=mysql_fetch_array($result1));
echo "<br>B <--<pre>";
print_r ($rows1);
echo "</pre><br><br>";
//////////////////////////////////////////////////////////
$result3=array_diff_assoc($rows,$rows1);
echo "<br>Users that didnt send in their dayreport<pre>";
print_r ($result3);
echo "</pre><br><br>"
This is what I have till now. And this works till so far.
Hourimport
id int(11) auto_increment
date datetime
employee int(11)
mail int(11)
status text
Assuming you have a table users with a primary key id column or something (and the user column is a number referencing users.id), and the day format is something that can be easily compared (for example date), you can do something like this:
SELECT * FROM users WHERE id NOT IN (SELECT DISTINCT(user) FROM hours WHERE day > :limit)
:limit is then a placeholder for the minimum day to filter against (I'm a Java guy and that's the syntax for JPA, for PHP I think it's $1 but you'll figure it out ^^)
First, you need a table of all the users who submitted their hours. Then you need a table of ALL the users.
What you would then do, is do RIGHT OUTER JOIN on the two tables. The resultset would give you the users who haven't submitted their hours mapped to nulls.

Best way to alert user

I have a database with a table called userbadges . All users have all badges at level 0 "locked" (greyed out) . They can unlock it at level 1 , all the way to level 3. Each level is worth points.
userbadges {user_id,badge_id,level,score,seen}
What would be the best way for me to alert the user that they
a) have unlocked a new badge
b) have leveled up a badge
I have this code , but it doesn't seem right. It counts the number of new badges ():
function countNewBadges() {
require "connect.php";
$newbadges = mysqli_query($connection,"SELECT users.studentid, individualbadges.badgename, ub.level, count(ub.seen) as total FROM userbadges ub
INNER JOIN users ON users.id = ub.user_id
INNER JOIN individualbadges ON individualbadges.id = ub.badge_id
WHERE studentid = '".$_SESSION["studentid"]."' && seen=0 && level!=0") or die(mysqli_error($connection));
while ($data = mysqli_fetch_array($newbadges)) {
echo $data['total'];
}
}
I also have code to set the seen field of the badges table to 1.
I would make a messaging system: Create a table message with text, title. (for every message you have or dynamicly) Then make a table user_has_message where you got the 2 Keys to join, and a boolean if read.
With a simple Select * from user JOIN user_has_message on ... and iduser = ... JOIN message on ... where read = false you get all your alerts/Messages for a specified user.
EDIT: Now you can simply add an entry to user_has_entry, in which you specify which user should get which message.
Now you have much possibilities: add the date with default NOW(), to know when the message occoured, give the user the possibility to delete this message (what only deletes the entry on the user_has_message), add tho option to mark a message as unread, etc etc ...
Shure you can also use those messages for other things like a Welcome-Message etc. Or add a cronjob to send an email to the users with open messages older than 5 days. Or even implement a chat-system...

Codeigniter 3 - Count rows from one table and join

I am trying to join two table and count all results from messageFiles which are related to message
I have tables with following structure:
messages:
id
name
email
subject
message
date_added
read
messagesFiles
id
name
message_id
date_added
I am trying this code, but I always get result countFiles = 1 and I message is repeated for every file that is related to it (for example if I have 3 files for the message, it will be repeated 3 times). Also messages which doesn't have files will not be selected by this query. What's seems to be a problem?
$this->db->select("SQL_CALC_FOUND_ROWS *, messages.*, COUNT(messagesFiles.id) as countFiles", FALSE)->from('messages')
->join('messagesFiles', "messagesFiles.message_id = messages.id")
->where("messages.read", 1)
->group_by('messagesFiles.id')->get()->result_array();
You could try some thing like this code below and add return $this->db->count_all_results().
http://www.codeigniter.com/docs
http://www.codeigniter.com/userguide2/database/active_record.html
public function count_test() {
$this->db->select("*");
$this->db->from('category c');
$this->db->join('category_description cd', "cd.category_id = c.category_id");
return $this->db->count_all_results();
}

MySQL Check for 3 or more consecutive entries

I have a live chat and i need to ban if the users chatted more than 5 times in a row
this is the sql:
function countMessages() {
global $tsUser;
$querys = db_exec(array(__FILE__, __LINE__), 'query', 'SELECT * FROM c_chat_messages where msg_user = "'.$tsUser->uid.'" ORDER BY msg_id ASC');
$counts = db_exec('num_rows', $querys);
if($counts > 5) { $this->banUser(); }
}
$tsUser->uid is the id of the user
i need to check if the user chatted for more than 5 times in a row so the php executes the $this->banUser(); function
you have to take timestamp of each message sent by the user in your database table.
And than you can fire a query checking if the user has sent more than 5 messages in last 15 seconds, by calculating the time different between the messages.
to get last five messages sent by that user,
SELECT * FROM c_chat_messages where msg_user = "'.$tsUser->uid.'" ORDER BY msg_id DESC limit 0,5
than get the difference between last and first record returned by above query.
to get time difference in seconds you can use
SELECT TIME_TO_SEC(TIMEDIFF('2010-08-20 12:01:00', '2010-08-20 12:00:00')) diff;
you can call a ajax file every one or two seconds to check this.
Let me know if further clarification needed.

Categories