Laravel Join with Where (Case) and AND - mysql

I'm having problem converting my SQL query to laravel queries. I want to join two tables users and messages so that i can get the users that has conversation with other users.
Database Structure:
Users:
Messages:
This is my SQL query where I get what I want:
SELECT u.id, c.id, u.first_name, u.last_name FROM messages c, users u
WHERE (CASE WHEN c.user_one = #USERID THEN c.user_two = u.ID WHEN c.user_two = #USERID THEN c.user_one= u.id END )
AND ( c.user_one = #USERID OR c.user_two = #USERID ) Order by c.id DESC Limit 20
This is my Laravel query:
DB::table('messages')
->join('users', function($join) use ($user_id) {
$join->select(DB::raw('CASE WHEN messages.user_one = ' . $user_id . ' THEN messages.user_two = ' . $user_id . 'WHEN messages.user_two = ' . $user_id . ' THEN messages.user_one = ' . $user_id));
$join->on(function($query) use ($user_id)
{
$query->where('messages.user_one', '=', $user_id);
$query->orWhere('messages.user_two', '=',$user_id);
});
})
->select('users.*', 'messages.*')
->get();

Related

Join in laravel with case and when statement

I've following query in Mysql :
SELECT
U.* FROM
`cr_friends` AS `cf` JOIN
`users` AS `U` WHERE
`cf`.`status` = 1
AND
(
CASE
WHEN `cf`.`friend_to` = 1 THEN `cf`.`friend_from` = `U`.`id`
WHEN `cf`.`friend_from` = 1 THEN `cf`.`friend_to` = `U`.`id`
END
) GROUP BY `U`.`id` ORDER BY `cf`.`created` desc;
I'm trying to put this in laravel in following way :
$myFriendsData = DB::table('cr_friends as cf')
->where('cf.status', '=', 1)
->Join('users as U')
->select(
DB::raw(
'(
CASE WHEN cf.friend_to = ' . auth()->user()->id . ' THEN cf.friend_from = U.id END
CASE WHEN cf.friend_from = ' . auth()->user()->id . ' THEN cf.friend_to = U.id END
)'
)
)
->select('U.*')
->orderBy('U.id', 'desc')
->get();
but didnt succeed as the mysql query is perfectly working fine but this laravel query wont.
Actually What I think is, there is problem with the Join which I'm putting in laravel it asking for one more parameter but in this case I'm unable to do that.
Can you guys please guide me so that I can achieve this.
Thanks
Randheer
Provide an empty closure for join() and use whereRaw():
$myFriendsData = DB::table('cr_friends as cf')
->where('cf.status', '=', 1)
->join('users as U', function() {})
->whereRaw(
'(
CASE
WHEN cf.friend_to = ' . auth()->user()->id . ' THEN cf.friend_from = U.id
WHEN cf.friend_from = ' . auth()->user()->id . ' THEN cf.friend_to = U.id
END
)'
)
->select('U.*')
->orderBy('U.id', 'desc')
->get();
I used the DB::raw for case end statement in join in Laravel Version 5.8
DB::table('users')
->join('settings', function ($join) {
$join->on('settings.id', '=', DB::raw(case when users.type = "admin" then users.admin_setting_id else users.setting_id end'));
})
->get();
use this
$myFriendsData = DB::table('cr_friends as cf')
->Join('users as U')
->where('cf.status', '=', 1)
->where(
DB::raw(
'(
CASE WHEN cf.friend_to = ' . auth()->user()->id . ' THEN cf.friend_from = U.id END
CASE WHEN cf.friend_from = ' . auth()->user()->id . ' THEN cf.friend_to = U.id END
)'
)
)
->select('U.*')
->orderBy('U.id', 'desc')
->get();

Options to update PDO Query

How i update this query?
I try get all category with more than 1 product, counting this products to show in her side, but my query is too slow (2s). How i do the same, if possible, but more faster?
SELECT
C.id, C.name, C.id_dept, C.cat_type, C.num_prod
FROM
(SELECT
C.id, C.name, C.id_dept, C.cat_type,
COALESCE((SELECT count(P.id) FROM Products P WHERE P.status = 1 AND P.promo = 1 AND P.id_cat = C.id ), 0) AS num_prod
FROM
Products_Cat C
) C
WHERE
C.num_prod > 0 AND C.cat_type = 1 AND C.id_dept = '{IDD}'
ORDER BY C.name ASC
Update PHP PDO
$sql = $db->prepare("UPDATE `Products` set `name` = :name, `id_dept` = :id_dept, `cat_type` = :cat_type WHERE status = 1 AND promo = 1);
//bind all parameters
$sql->bindParam(':name',$name);
.
.
.
$sql->execute();

Long tail where clause at CodeIgniter or Ignited Datatables

I am trying to write a long tail where statement which containing another select query and how I can do it. Currently, I am using Ignited Datatables Library with my CodeIgniter 3 installation.
SELECT ContactId,
ReceiverId,
SenderId,
IF(ReceiverId = 1,
(SELECT first_name
FROM users
WHERE users.id = contacts_connectivity.SenderId),
(SELECT first_name
FROM users
WHERE users.id = contacts_connectivity.ReceiverId)) AS FirstName,
IF(ReceiverId = 1,
(SELECT email
FROM users
WHERE users.id = contacts_connectivity.SenderId),
(SELECT email
FROM users
WHERE users.id = contacts_connectivity.ReceiverId)) AS SenderEmail,
IF(ReceiverId = 1,
(SELECT phone
FROM users
WHERE users.id = contacts_connectivity.SenderId),
(SELECT phone
FROM users
WHERE users.id = contacts_connectivity.ReceiverId)) AS SenderPhone,
IF(ReceiverId = 1,
(SELECT company
FROM users
WHERE users.id = contacts_connectivity.SenderId),
(SELECT company
FROM users
WHERE users.id = contacts_connectivity.ReceiverId)) AS SenderCompany,
ModulesId,
(SELECT ModuleName
FROM modules
WHERE ModuleId = contacts_connectivity.ModulesId) AS ModuledName,
FROM_UNIXTIME(AddedDate, "%m/%d/%Y") AddedDate
FROM contacts_connectivity
WHERE (ReceiverId = 1
OR SenderId = 1)
AND (ReceiverId
OR SenderId NOT IN
(SELECT (ReceiverId
OR SenderId)
FROM contacts_connectivity
WHERE (ReceiverId
OR SenderId) = 1))
I noticed that My query doesn't return any array at all. I already tried to write the where statement like this-
$this->datatables->where("(ReceiverId = ' . $id . ' OR SenderId = ' . $id . ')");
$this->datatables->where(" AND (ReceiverId OR SenderId NOT IN (SELECT (ReceiverId OR SenderId) FROM contacts_connectivity WHERE (ReceiverId OR SenderId) = ' . $id . '");
What am I doing wrong?
You invalid use parameters. Try something like this:
$this->datatables->where("(ReceiverId=$id OR SenderId=$id )");
Second string should be fixed too the same way. Also check that your $id param properly escaped.

Display different results on different page/profiles

I dont know if I lost the information in my brain, or if I never had it, but I have created a tweet so a user can follow other users.
The problem now is that every user display the same information.
I Was trying to add WHERE $_SESSION['uid'] to my query but that doesn't help do the trick.
Still shows the same info.
Any tips ?
<?php
foreach(fetch_follotweets() as $tweet){
echo $tweet['firstname'];
echo $tweet['lastname'];
echo $tweet['username'];
echo $tweet['date'];
echo $tweet['profile_img'];
$tweet['message'];
}
function fetch_follotweets(){
global $db;
$query = $db->query(" SELECT
user.email,
user.username,
tweets.message,
tweets.date,
userdetails.profile_img,
userdetails.firstname,
userdetails.lastname,
following.id,
following.user_id,
following.follow_id
FROM user
JOIN userdetails
ON user.id = userdetails.user_id
JOIN tweets
ON userdetails.user_id = tweets.user_id
JOIN following
ON following.follow_id
WHERE following.follow_id = tweets.user_id AND
user.id='{$_SESSION['uid']}
ORDER BY tweets.date DESC");
$tweet = array();
while(($row = $query->fetch(PDO::FETCH_ASSOC)) !==FALSE) {
$tweet[] = $row;
}
return $tweet;
}
?>
Without the WHERE clause, the SQL would get the details of all the users
Also, I think that the JOIN on tweets & following should be a LEFT JOIN ( to get the records even if none of them is present )
SELECT
user.email,
user.username,
tweets.message,
tweets.date,
userdetails.profile_img,
userdetails.firstname,
userdetails.lastname,
t.ids_of_users_followed
FROM
user
JOIN userdetails
ON user.id = userdetails.user_id
LEFT JOIN (
SELECT
GROUP_CONCAT( following.follow_id ) AS ids_of_users_followed
following.user_id
FROM
following
GROUP BY
following.user_id
) as t ON ( t.user_id = user.id )
JOIN tweets
ON ( userdetails.user_id = tweets.user_id OR FIND_IN_SET( tweets.user_id, t.ids_of_users_followed ) )
WHERE
user.id = :? => Make sure to add the logged in user_id here
ORDER BY
tweets.date DESC

How to display rows from MySQL not older than a day?

I want to display news, for example from yesterday. Here's what my query looks like. Is there any magical line of code which would do that?
$query = '
SELECT a.*,
CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(":", a.id, a.alias)
ELSE a.id END as slug,
CASE WHEN CHAR_LENGTH(b.alias) THEN CONCAT_WS(":", b.id, b.alias)
ELSE b.id END as catslug,
b.title as category_title,
b.alias as categoryalias,
b.params as categoryparams,
u.name AS author
FROM #__content as a
LEFT JOIN #__categories as b ON a.catid = b.id
LEFT JOIN #__users AS u ON u.id = a.created_by
WHERE ' . $where. '
ORDER BY ' . $orderby. '
LIMIT ' . $limit;
The "magical" line of code should be in your WHERE clause.
e.g. if you date is only YYYY-MM-DD
$query .= 'WHERE b.created_date = '.$db->quote( date('Y-m-d', strtotime('-1 day')) ).'
e.g. if your date column is YYYY-MM-DD H:i:s
$query .= 'WHERE DATE_FORMAT(b.created_date,"%Y-%m-%d") = '.$db->quote( date('Y-m-d', strtotime('-1 day')) ).'