unique field from mysql database to php - php

I have a sample database like this, in which, id is always unique, but the user_id is not unique.
id,user_id,message,msg_datetime
111,u1, msg from u1,time present here
112,u2, msg from u2,time present here
113,u3, msg from u3,time present here
114,u2, msg from u2,time present here
115,u7, msg from u7,time present here
116,u2, msg from u2,time present here
117,u1, msg from u1,time present here
118,u5, msg from u5,time present here
so i want to grab only those unique users who have messaged and order them in DESC by msg_datetime.
This is the query i have.
select id,DISTINCT user_id,msg_datetime ORDER BY msg_datetime DESC but i am getting an error as:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DISTINCT. any help here? what is the correct syntax for what i am trying to achieve?
I want to show only one entry for each user, it does not matter which ID i am showing but only 1 per user.

If you don't care which record with the same user_id query should return, then
SELECT id,user_id,msg_datetime FROM table_1 GROUP BY user_id ORDER BY msg_datetime DESC
If you want to display, for instance, the last record for each user, you need
SELECT a.user_id, a.last_time, b.id
FROM
(SELECT user_id, MAX(msg_datetime) as last_time
FROM table1)a
INNER JOIN table1 b ON (b.user_id = a.user_id AND b.msg_datetime = a.last_time)
ORDER BY a.last_time;

SELECT syntax:
SELECT (fieldlists)
FROM (table)
[WHERE (conditions)]
ORDER BY (something)
You kindof forgot to say which table you want the data from.

You misunderstand how DISTINCT works. It works on rows not fields. What you want is a groupwise maximum, also known as greatest-n-per-group.
Here's one way to do it in MySQL:
SELECT id, user_id, message, msg_datetime
FROM (
SELECT
id, user_id, message, msg_datetime,
#rn := CASE WHEN #prev_user_id = user_id
THEN #rn + 1
ELSE 1
END AS rn,
#prev_user_id := user_id
FROM (SELECT #prev_user_id := NULL) vars, Table1 T1
ORDER BY user_id, msg_datetime DESC
) T2
WHERE rn = 1
ORDER BY msg_datetime

Related

Mysql Retrieve Specific Number of grouped rows from a join

So I created this query
SELECT a.email
, a.password
, a.server
, a.status
, a.step
, b.*
FROM mail a
JOIN automation_logs b
ON b.accountid = a.accountid
WHERE a.status <0
ORDER
BY b.created DESC;
What it's used for is essentially I'm trying to get debug information from our log table for email accounts that are errored out on our api. The automation_logs table essentially is text dump of error messages that were produced by our API.
This query gives me what I want but gives me too much. I only want the last five most recent (read: created field is a timestamp) error messages for any of the accounts as some of these accounts have existed for years and old errors have been fixed and aren't necessary to know what's broken and just pad the results.
Is this possible with a single query?
Following the advice listed here: Thank you Marshal Tigerus
I was able to get it to work with the following sql:
SET #currcount = NULL, #currvalue = NULL;
SELECT a.email,a.password,a.serverid,a.status,a.step,b.message,b.created FROM mail as a JOIN (
SELECT * FROM (
SELECT
*,
#currcount := IF(#currvalue = accountid, #currcount + 1, 1) AS num,
#currvalue := accountid AS cur_id
FROM automation_logs
WHERE message NOT LIKE ""
ORDER BY accountid, created DESC
) as limitedresults WHERE num <= 5
) as b ON a.accountid = b.accountid WHERE a.status < 0 ORDER BY b.created DESC

Select max value for a VARCHAR column - MySQL

My table for message inbox concept email is a primary in the table. I want to get the last message which is sent by particular email.
tbl_msg:
id
email
msg
Example Data:
Id email msg
1 xyz#gmail.com This is test
2 abc#gmail.com All is well
3 xyz#gmail.com This is test2
I want to get the last appearance of each email and msg
Id email msg
2 abc#gmail.com All is well
3 xyz#gmail.com This is test2
What I tried:
SELECT cnote.`id`,cnote.`email`,cnote.`msg` FROM `tbl_msg` cnote inner join (select distinct email,id from client_com group by email) as note
on cnote.id=note.id
Guide me if I wrong
Use This query:
SELECT m1.* FROM tbl_msgs m1 LEFT JOIN tbl_msgs m2 ON (m1.email = m2.email AND m1.id < m2.id) WHERE m2.id IS NULL;
This will join with the same table and with condition m1.id < m2.id , will get the latest one.
Another option is using subquery:
SELECT * FROM tbl_msgs WHERE id IN (SELECT MAX(id) FROM tbl_msgs GROUP BY email);
To get the latest messsage for each email address in the table you do not need a JOIN, you just need to ORDER and GROUP BY:
SELECT `id`, `email`, `msg`
FROM `tbl_msg`
GROUP BY `email`
ORDER BY `id` DESC
You can use this query:
SELECT id, email, msg FROM you_table
GROUP BY email
ORDER BY id DESC
With this one you will have only 1 row per email, and you'll have the last because is ordered by id DESC.
If you are running a PDO connection (The way I know to do it, not sure if there is a MySQLi way)
$theLastIdGiven = $handlerDbConnection->lastInsertId();
Or if you want to run it through a query, and get the last result, just add ORDER BY id DESC LIMIT 0, 1 and that will order the data by id in a descending form then get the first bit of data :)
Hope this helped you!
SELECT ID, email, Msg FROM tbl_msg WHERE ID IN (
(SELECT MAX(ID) FROM tbl_msg GROUP BY email))

query to Ignore the repeated column in leaderboard

i have a problem my database looks like this DATABASE STRUCTURE
i want to sort the lboard and ignore the repeated values
like this REQUIRED OUTPUT
can anyone help me?
You could use GROUP BY to get single result for one user and MAX function to get its maximum score
the query will be like this
SELECT id, exam_id, user_id, MAX(lboard) FROM `leaderb` GROUP BY user_id ORDER BY lboard DESC
SELECT id, exam_id, user_id, MAX( lboard )
FROM wp_watu_takings WHERE exam_id = 3
GROUP BY user_id
ORDER BY MAX( lboard ) DESC

Want to delete any unique userid has more than 50 items

I have a table with named "user-recent-activity" which has following columns: id, userid, activity and datetime. Now, I want to delete the records if any unique userid has more than 50 items, deleting the oldest records. For example, if the user id(lets say 1234) has more than 50 records in this table, then I have to save latest 50 records of user id(1234) and delete the oldest one.
Before inserting, query for the last 50 records with that ID (ordering from newer to older). If there is a 50th, substitute it (via update) instead of inserting a new row.
Assuming you are using a RDBMS that supports standard SQL the following stored procedure should do it.
create procedure remove-old-activities
(
#userid int
)
as
delete from user-recent-activity where userid=#userid and id not in (select top 50 id from user-recent-activity where userid=#userid order by datetime desc)
If you're DB does not support stored procedures then you should be able to use SQL parameters to pass the userid value...
Hope that helps
You could use rank method to precisely defined the rows number and thus delete the rows you want.
delete from tblName where id=
(select id from (
select #i := CASE WHEN ( #userid <> userid ) THEN 1
ELSE #i+1
END AS rank , id,userid, datetime2 ,#userid:=userid AS clset
from tblName x,(SELECT #i:=0) a ,(SELECT #userid:= 0) s
order by x.userid, datetime2 desc) T
where T.rank='50') ;
Another option:
Use the select query to select the rank <=50 and insert into a new table. Delete the old table and rename the new table afterwards.
insert into newtable (userid,activity,datetime2)
select userid,datetime2 from (
select #i := CASE WHEN ( #userid <> userid ) THEN 1
ELSE
#i+1
END AS rank , userid, activity,datetime2 ,#userid:=userid AS clset
from tblName x,(SELECT #i:=0) a ,(SELECT #userid:= 0) s
order by x.userid, datetime2 desc) T
where t.rank <=50

PHP / MySQL Checking data between tables with long query

This is a more detailed question as my previous attempt wasn't clear enough. I'm new to MySQL and have no idea about the best way to do certain things. I'm building a voting application for images and am having trouble with some of the finer points of MySQL
My db
_votes
id
voter_id
image_id
_images
id
file_name
entrant_id
approved
_users
id
...
Basically I need to do the following:
tally up all votes that are approved
return the top 5 with the most votes
check if the user has voted on each of these 5 (return Boolean) from another table
I've tried variations of
SELECT i.id, i.file_name, i.total_votes
FROM _images i WHERE i.approved = 1
CASE WHEN (SELECT count(*) from _votes v WHERE v.image_id = i.id AND v.voter_id = ?) > 0 THEN '1' ELSE '0' END 'hasvoted'
ORDER BY i.total_votes DESC LIMIT ".($page*5).", 5
is that something I should try and do all in one query?
This query was working fine before I tried to add in the 'hasvoted' boolean:
SELECT id, file_name, total_votes FROM _images WHERE approved = 1 ORDER BY total_votes DESC LIMIT ".($page*5).", 5
At the moment I'm also storing the vote count in the _images table and I know this is wrong, but I have no idea about how to tally the votes by image_id and then order them.
Let me give this a shot to see if I understand your question:
SELECT i.*,(SELECT COUNT(*) FROM _votes WHERE i.id = image_id) AS total_votes, (SELECT count(*) from _votes where i.id = image_id and user_id = ?) as voted FROM _images AS i WHERE i.approved = 1

Categories