How to get last record of duplicate data? - mysql

I have table A ( id - message - user_id ), I need to say if any user_id duplicated in table just bring last one that user had added:
My controller code (my wrong shut):
$duplicate = VerfiyRequest::where('user_id', '>' , 1)->first();
$VerfiyRequests = VerfiyRequest::latest()->get();
return view('backend.VerfiyRequest.index' , compact('VerfiyRequests'));

Use this to get the last record of each user by the latest id (incrementing primary key):
VerfiyRequest::whereIn('id', function ($query) {
$query
->from('verify_requests')
->select(DB::raw('MAX(id) as id'))
->groupBy('user_id');
})->get();
Explanation: the MAX(id) as id selects latest id of each user group, so the inner query returns latest record of each user.

Related

Laravel eloquent where current status is equals to string

I have a candidate and a status table which every candidate have multiple statuses. when statuses changes new row in statuses table will be created to store new status. So when user wants to filter candidates by status I want to select candidates that their current status is what user select not the all before statuses.
my query is :
$status = $request->get('status');
$q->where(function ($q) use ($status) {
$q->orWhereHas('statuses', function ($q) use ($status) {
$q->where('status', 'like', "%" . $status . "%");
});
});
I changed the query to the blow and it's working fine.
$q->whereRaw('status LIKE "%'.$status.'%" AND id=(select max(id) from statuses WHERE status LIKE "%'.$status.'%")');
EDIT:
The query in above has a problem and that is it's only get's first matching candidate not all of them so I changed the query to this:
$q->where(function ($q) use ($status) {
$q->orWhereHas('statuses', function ($q) use ($status) {
$q->whereRaw('status LIKE ? AND id IN (SELECT MAX(id) FROM statuses GROUP BY candidate_id)',["%".$status."%"]);
});
});
my percipience is, current status of a candidate is last record.
i say mysql direction, as for your migrate and modeling, implement this.
select * from status
where id =(
select max(id) from status
where candidate_id= x
)
x is candidate id.

How to fetch records from two different tables in laravel5.2

I have two tables 'approval' and 'renewal', both having a common column 'applicant_id'.
When new application comes-in, it stores a data-record in table 'approval' alongwith the 'applicant_id' for whom the record has been added.
Now, when there is a renew applied for that same applicant, the row gets created in the table 'renewal' referencing the 'applicant_id'
Note: There can be a single record in the table 'approval' for a 'applicant_id' but there can be more than one record for the same 'applicant_id' in the table 'renewal'.
Now, my requirement is:
I need to fetch the records from both the table for all the applicants.
Conditions: If there is a data for the 'applicant_id' in both the table and 'renewal' table has multiple row for the same 'applicant_id', then I need to get the records from 'renewal' table only that too the latest one.
If there is no data in 'renewal' table but exists in 'approval' table for the 'applicant_id', then the fetch record should get the data present in 'approval' table.
Basically, if there is record for the applicant in 'renewal' table, get the latest one from there, if there is record present only in 'approval' table, then get that one but the preference should be to get from 'renewal' if exists.
I am trying to do this in laravel 5.2. So, is there anyone who can help me in this?
If you're using Eloquent, you'll have 2 models:
Renewal.php
<?php
namespace App;
use Illuminate\Eloquent\Model;
class Renewal extends Model
{
protected $table = 'renewal';
public static function findMostRecentByApplicantId($applicantId)
{
$applicant = self::where('applicant_id', '=', $applicantId)
->orderBy('date_created', 'desc')
->first();
return $applicant;
}
}
Approval.php
<?php
namespace App;
use Illuminate\Eloquent\Model;
class Approval extends Model
{
protected $table = 'approval';
public static function findByApplicantId($applicantId)
{
$applicant = self::where('applicant_id', '=', $applicantId)
->first();
return $applicant;
}
}
Then, in the code where you want to get the approval/renewal record, use the following code:
if (! $record = Renewal::findMostRecentByApplicantId($applicantId)) {
$record = Approval::findByApplicantId($applicantId);
}
//$record will now either contain a valid record (approval or renewal)
//or will be NULL if no record exists for the specified $applicantId
After few try, I got one way to do it using raw:
SELECT applicant_id, applicant_name, applicant_email, applicant_phone, renewed, updated_at
FROM (
SELECT renewal_informations.applicant_id, renewal_informations.applicant_name, renewal_informations.applicant_email, renewal_informations.applicant_phone, renewal_informations.renewed, renewal_informations.updated_at
FROM renewal_informations
UNION ALL
SELECT approval_informations.applicant_id, approval_informations.applicant_name, approval_informations.applicant_email, approval_informations.applicant_phone, approval_informations.renewed, approval_informations.updated_at
FROM approval_informations
) result
GROUP BY applicant_id
ORDER BY applicant_id ASC, updated_at DESC;
For every single Approval id, there can b multiple records for renewal table suggests you have One to Many relation. which you can define in the your Model like
Approval.php (App\Models\Approval)
public function renewal()
{
return $this->hasMany('App\Models\Renewal', 'applicant_id')
}
Having defined this relation. you can get the records from the table using applicant_id.
$renewal_request_records = Approval::find($applicant_id)->renewal();
This will get all records from renewal table against that applicant_id.
Finding the latest
$latest = Renewal::orderBy('desc', 'renewal_id')->first();
Further Readings Eloquent Relations

how do i achieve following condition in codeigniter sql?

I have a table with the name message_system.
and structure of the table is as follow:
message_system => message_id(primary key)->sender_id->receiver_id->
message->time(current time stamp)
lets consider a $user_id = 1 and I want to select the row from the table
something like
select * from message_system where sender_id = $user_id or receiver_id = $user_id
and from the yielded result I want select only single result which has recently stored according to time stamp.
actually I want to select recent message from the message thread between two user..
edit 1:
I want to get recent message from the table with respect to each
unique pair of (user1_id and user2_id). Either it is(user1_id,
user2_id) or (user2_id, user1_id) usually user id of logged in user
would be on of the id and another is id of user who have been
messaged to current logged in user.
edit 2:
example:
lets consider user1 is logged in and he has messaged to user2. and later messaged to user3 and user4.
and those all messages are stored in the table and now i want to query such that it retrieves only recent message with user2,user3,user4 in user1 wall. not all their history
edit 3 :
query should return recent message of logged in user with user1 and recent message of logged in user user2 and user3 so on.
thank you for your time.
select * from message_system where sender_id = $user_id or receiver_id = $user_id
would translate in CodeIgniter in:
$this->db->where('sender_id', $user_id);
$this->db->or_where('receiver_id', $user_id);
$query = $this->db->get('message_system');
$row = $query->row();
If you want the most recent input, you could order by time, and if you know you only need one row, limit to 1:
$this->db->where('sender_id', $user_id);
$this->db->or_where('receiver_id', $user_id);
$this->db->order_by('time', 'desc');//order by time
$this->db->limit('1');//limit the query to only one row
$query = $this->db->get('message_system');
$row = $query->row();// get only first
UPDATE:
The solution above works if you want to find one entry corresponding to one given user.
If you want to find last entry for a given pair of users, thing would look like this if unknown who would be the sender and who would be te receiver:
$this->db->where_in('sender_id', array($user_id1, $user_id2));
$this->db->where_in('receiver_id', array($user_id1, $user_id2));
$this->db->order_by('time', 'desc');//order by time
$this->db->limit('1');//limit the query to only one row
$query = $this->db->get('message_system');
$row = $query->row();// get only first
And like this if you know exactly who is who:
$this->db->where('sender_id', $user_id1);
$this->db->where('receiver_id', $user_id2);
$this->db->order_by('time', 'desc');//order by time
$this->db->limit('1');//limit the query to only one row
$query = $this->db->get('message_system');
$row = $query->row();// get only first
With little bit modification of the table I have come up with an idea.
earlier my table structure was:
message_system => message_id(primary key)->sender_id->receiver_id->
message->time(current time stamp)
after modification:
message_system => message_id(primary key)->sender_id->receiver_id->
message->time(current time stamp)->unique_pair_key
unique_pair_key is to identify the message between two user uniquely and value would be something like this ($sender_id^2 + $receiver_id^2)
which is unique for given pair.
all messages between two particular user would be identify by this unique_pair_key.
so taking logged_in user as the reference, with respect to him only recent message with different user (if there any) should be shown (similar to stack overflow recent inbox message )and on clicking that particular message it should direct to their message thread.
model/model.php
public function get_notification($user_id)
{
$this->db->where("receiver_id",$user_id);
$this->db->where("sender_id",$user_id);
//because recent message would either be sent or received by logged in user
$this->db->select_max('message_id');
// latest message would have greatest value of id
$this->db->group_by('unique_pair_key');
$query = $this->db->get('message_system ');
//returns latest message_id with unique pair in which on of them is $userid.
}
above query only generates message id with that we can further query to get message
If you have any better solution please share with us.

Codeigniter active record join with 3 tables

I have 3 tables,
user - contains user_id | username | fullname | email etcc
user_profile - contains entry_id |user_id| profile_image_id| user_location etcc
user_profile_images - contains image_id| user_id | file_path | file_thumb | date etcc
When a user sign's up, all the details go to the users table, the user_id is also added to the user_profile table with the rest set default as NULL till the user add's some profile info.
I have a query in model_users to get all user's data from these three table and it goes like this;
$this->db->where('users.user_id', $user_id)->select('*')->from('users');
$this->db->join('user_profile', 'user_profile.user_id = users.user_id', 'left');
$this->db->join('user_profile_images','user_profile_images.image_id = user_profile.profile_image_id','left');
It work's fine only when the profile_image_id field in user_profile is not null, that is when the user has uploaded a pic. In the case where the field is null, the user user_id is not returned even when all the other data are returned.
I can see why this is the case, as my join query requires the field profile_image_id but currently my way around it was to set profile_image_id in user_profile as 1(default), which is the default image and has image_id as 1 and user_id as 0 as it's the general default image. But i still can't get over the fact that i need to update that query to make it less of a hack.
Do you guys have any ideas?
Try
$this->db->select('*')->select('users.user_id')->from('users')
->join('user_profile', 'user_profile.user_id = users.user_id', 'LEFT')
->join('user_profile_images', 'user_profile_images.image_id = user_profile.profile_image_id', 'LEFT')
->group_by('users.user_id')
->where('users.user_id', $user_id);
$query = $this->db->get();
When using join for tables you need your columns in all joined tables to have unique names. Either you add column aliases by AS syntax or just retrieve the columns you need. In your case the error is most probably due to the fact that user_id exists in all three tables. Hence the result is like you experience. user_id is retrieved only for the last occurrence and that is if your user has uploaded an image. I would alter the query someting like:
$this->db->where('users.user_id', $user_id);
$this->db->select('users.*,user_profile.user_location,user_profile_images.filepath'); // and other fields of interest...
$this->db->from('users');
$this->db->group_by('users.user_id'); // very useful for not getting multiple rows/user
$this->db->join('user_profile', 'user_profile.user_id = users.user_id', 'left');
$this->db->join('user_profile_images','user_profile_images.image_id = user_profile.profile_image_id','left');
Try This one.
$this->db->select("*");
$this->db->from('table1');
$this->db->join('table2','table2.id1=table1.id1');
$this->db->join('table3','table3.id1=table1.id1');
$query = $this->db->get();
return $query->result();

How to make a 1 column query by choosing from two columns mysql

I have a messaging system (very basic) that has a table like this:
**MESSAGE_ID** **RUSER_ID** **SUSER_ID** **MESSAGE_DATA** **DATE**
RUSER is the receiving user, and SUSER is the sending user. If I wanted to output a query that would output a certain users messages, I would currently do:
Select * from PRIVATE_MESG where RUSER_ID=$USER_ID or SUSER_ID=$USER_ID
That would give me all message_id's that are associated with that USER_ID. What I would like, is to create a column that would produce only the ID associated with RUSER_ID or SUSER_ID associated with a specific user. I need it to choose the messages that RUSER_ID or SUSER_ID are equal to a USER_ID but only display the one that isn't USER_ID
I would then like to do a group by the output of that query.
Any help is greatly appreciated!
Thanks!
update I am not really looking for a message_id, I am just looking for a list of users who that person has written to or received from.
UPDATE
Just so everyone knows, I recieved the answer to this question perfectly! I tweaked it later on so that it would also display them by date from newest to oldest. I did this by spliting the DATETIME into DATE and TIME USING the DATE() and TIME() Function. Here was my final query:
SELECT
IF(RUSER_ID = $USER, SUSER_ID, RUSER_ID) as THE_OTHER_GUY, DATE(DATE) as DAY, TIME(DATE) as TIME
FROM PRIVATE_MESG
WHERE RUSER_ID = $USER
OR SUSER_ID = $USER;
group by THE_OTHER_GUY ORDER BY DAY DESC, TIME DESC
Hope this helps the next person!
You can query:
SELECT
*,
IF(RUSER_ID = $USER_ID, SUSER_ID, RUSER_ID) as THE_OTHER_GUY
FROM PRIVATE_MESG
WHERE RUSER_ID = $USER_ID
OR SUSER_ID = $USER_ID;
SELECT SUSER_ID FROM PRIVATE_MESG WHERE RUSER_ID=$USER_ID
UNION
SELECT RUSER_ID FROM PRIVATE_MESG WHERE SUSER_ID=$USER_ID
It retrieves:
- the list of user IDs who sent messages to $USER_ID
- the list of user IDs who received messages from $USER_ID
And UNION groups the 2 lists in a single result set.