Convert a Mysql query to Laravel 5 Eloquent? - mysql

I am using Laravel 5.1 in my application. My MySQL query is
"Select * from "
. "(Select u.* from "
. "( "
. "SELECT u2.id as user_id, u2.fname as fname, u2.lname as lname, u2.uname as uname, u2.email as email, u2.address as address, u2.city_id as city_id, u2.website as website FROM users u1, users u2 where u1.city_id = u2.city_id && u1.id = '$this->current_user_id' )
u left join follows f on u.user_id = f.following_id where f.following_id is null
UNION
Select uu.id as user_id, uu.fname as fname, uu.lname as lname, uu.uname as uname, uu.email as email, uu.address as address, uu.city_id as city_id, uu.website as website from users uu where uu.id in (Select u.user_id from (SELECT user_id FROM reviews group by user_id order by count(user_id) desc5
) u left join follows f on u.user_id=f.following_id where f.following_id is null
)
)
T LIMIT 5"
How can I convert it into Laravel Eloquent?

Is that query functionally identical to this one:
SELECT u2.id user_id
, u2.fname
, u2.lname
, u2.uname
, u2.email
, u2.address
, u2.city_id
, u2.website
FROM users u1
JOIN users u2
ON u2.city_id = u1.city_id
LEFT
JOIN follows f
ON f.following_id = u.user_id
WHERE f.following_id is null
UNION
SELECT uu.id user_id
, uu.fname
, uu.lname
, uu.uname
, uu.email
, uu.address
, uu.city_id
, uu.website
FROM users uu
JOIN
( SELECT r.user_id
FROM reviews r
LEFT
JOIN follows f
ON f.following_id = r.user_id
WHERE f.following_id IS NULL
GROUP
BY user_id
ORDER
BY COUNT(user_id) DESC
LIMIT 5
) x
ON x.user_id = uu.id;
?

Related

Get most recent MySQL transaction only

I'm trying to export a set of user information from one WordPress database to import into another database. However I'm having trouble figuring out how to only export the most recent membership transaction for a user. The following query exports all transactions for each user, but I only want the transaction with the most recent "t.expires_at" value. I've tried various sub-queries etc based on other StackOverflow threads but can't quite figure it out.
SELECT DISTINCT
u.user_login AS user_login,
u.user_email AS user_email,
u.user_registered AS user_registered,
f.meta_value AS first_name,
l.meta_value AS last_name,
t.expires_at AS membership_enddate
FROM
wp_acfzia_users AS u
LEFT JOIN
wp_acfzia_usermeta AS f
ON u.ID = f.user_id AND f.meta_key = 'first_name'
LEFT JOIN
wp_acfzia_usermeta AS l
ON u.ID = l.user_id AND l.meta_key = 'last_name'
LEFT JOIN
wp_acfzia_mepr_transactions AS t
ON u.ID = t.user_id
Try this approach
SELECT DISTINCT
u.user_login AS user_login,
u.user_email AS user_email,
u.user_registered AS user_registered,
f.meta_value AS first_name,
l.meta_value AS last_name,
t.expires_at AS membership_enddate
FROM
wp_acfzia_users AS u
LEFT JOIN
wp_acfzia_usermeta AS f
ON u.ID = f.user_id AND f.meta_key = 'first_name'
LEFT JOIN
wp_acfzia_usermeta AS l
ON u.ID = l.user_id AND l.meta_key = 'last_name'
LEFT JOIN
wp_acfzia_mepr_transactions AS t
ON u.ID = t.user_id
WHERE exists (
select 1 from tbl where tbl.user_id = t.user_id
having max(tbl.expires_at) = t.expires_at
)
or MySQL 8+
select * from (
SELECT DISTINCT
u.user_login AS user_login,
u.user_email AS user_email,
u.user_registered AS user_registered,
f.meta_value AS first_name,
l.meta_value AS last_name,
t.expires_at AS membership_enddate,
row_number() over (order by t.expires_at partition by user_id) rn
FROM
wp_acfzia_users AS u
LEFT JOIN
wp_acfzia_usermeta AS f
ON u.ID = f.user_id AND f.meta_key = 'first_name'
LEFT JOIN
wp_acfzia_usermeta AS l
ON u.ID = l.user_id AND l.meta_key = 'last_name'
LEFT JOIN
wp_acfzia_mepr_transactions AS t
ON u.ID = t.user_id
)
Where rn = 1

mysql query taking long time to respond

SELECT t.id
, t.department
, t.owner
, t.client
, u.username as owner_name
, c.name as catagery
, d.dept_name as deptname
, t.periority
, t.status
, t.estimate
, cl.takeaway_name
from tbl_task t
JOIN tbl_user u
ON u.id = t.owner
JOIN tbl_task_catagery c
ON c.id = t.catagery
JOIN tbl_department d
ON d.id = t.department
JOIN tbl_clients cl
ON cl.id = t.client
and t.status = 0
and (t.id in (select task_id
from tbl_task_note tn
where tn.user_id = '69'
and tn.id in (select max(id)
from tbl_task_note tt
where tt.task_id = tn.task_id
)
)
)
order by t.id
Note : The above query is used for check users hold tasks. tbl_task_note table is used for check task notes for separate users task.
With this query you will get the task that have the last task_note registered, including the user, departament, client, and some other.
If it is what you need you can just do this.
select
t.id,
t.department,
t.owner,
t.client,
u.username as owner_name,
c.name as catagery,
d.dept_name as ptname,
t.periority,
t.status,
t.estimate,
cl.takeaway_name
from tbl_task t
INNER JOIN tbl_user u ON u.id=t.owner
INNER JOIN tbl_task_catagery c ON c.id=t.catagery
INNER JOIN tbl_department d ON d.id=t.department
INNER JOIN tbl_clients cl ON cl.id=t.client and t.status=0
INNER JOIN (select * from tbl_task_note where id =
(select max(id) from tbl_task_note)
)tb on tb.task_id = t.id
order by t.id
That way you can improve your query.
You shoud also ensure that your keys compared are foreign keys to get faster consults.

Extremely slow query

Below is a query which takes 30+ seconds to run. Based on similar queries I have running, I can't see where the hold up is here. My only thought is joining the job user id to job_applicants user id, but they need to be mapped.
SELECT DISTINCT u.user_id, u.first_name, u.last_name FROM users u
LEFT OUTER JOIN employee_access ea ON ea.user_id = u.user_id
LEFT OUTER JOIN confirmation c ON c.user_id = u.user_id
LEFT OUTER JOIN job_applicants a ON a.user_id = u.user_id
LEFT OUTER JOIN job j ON j.job_id = a.job_id
WHERE ea.access_id = 4 OR c.access_id = 4 OR (a.process_level = 0 AND j.access_id = 4)
ORDER BY u.last_name asc
Use exists:
select u.*
from users u
where exists (select 1
from employee_access ea
where ea.user_id = u.user_id and ea.access_id = 4
) or
exists (select 1
from confirmation c
where c.user_id = u.user_id and c.access_id = 4
) or
exists (select 1
from job_applicants a join
job j
on j.job_id = a.job_id
where a.user_id = u.user_id and
a.process_level = 0 AND j.access_id = 4
)
order by u.last_name;
This will prevent all the Cartesian products and the final removal of duplicates.
I would recommend indexes on:
users(last_name, user_id)
employee_access(user_id, access_id)
confirmation(user_id, access_id)
job_applicants(user_id, process_level, job_id)
job(job_id, access_id)
Yet another approach. This has the advantage of first gathering the list of user_ids, then reaching into users for the other columns:
SELECT u.user_id, u.first_name, u.last_name
FROM users u
JOIN (
( SELECT user_id FROM employee_access WHERE access_id = 4 )
UNION DISTINCT
( SELECT user_id FROM confirmation WHERE access_id = 4 )
UNION DISTINCT
( SELECT a.user_id
FROM job_applicants a
JOIN job j USING(job_id)
WHERE a.process_level = 0
AND j.access_id = 4 )
) AS x USING(user_id)
ORDER BY u.last_name ASC
Indexes:
employee_access: INDEX(access_id, user_id) -- (covering)
confirmation: INDEX(access_id, user_id) -- (covering)
job: INDEX(access_id, job_id) -- (covering)
job_applicants: INDEX(process_level, job_id, user_id) -- (covering)
users: PRIMARY KEY(user_id)
See if this will shave off most of the remaining 8 seconds.
This should work. It is similar in concept to Gordon's answer but I have a borderline pathological distrust of correlated subqueries.
SELECT DISTINCT u.user_id, u.first_name, u.last_name
FROM users u
WHERE u.user_id IN (SELECT user_id FROM employee_access WHERE access_id = 4)
OR u.user_id IN (SELECT user_id FROM confirmation WHERE access_id = 4)
OR u.user_id IN (
SELECT a.user_id
FROM job_applicants a
INNER JOIN job j ON j.job_id = a.job_id
WHERE a.process_level = 0 AND j.access_id = 4
)
ORDER BY u.last_name asc

trying to fetch the last message in mysql

This is my query:
SELECT u.ProfilePic AS FriendPic, u.UserName AS FriendName, m.*
FROM (SELECT PhotographerId
FROM Messages
WHERE UserId=? OR PhotographerId=?
GROUP BY PhotographerId
) AS m JOIN
User AS u
ON u.UserId = m.PhotographerId;
I'm trying to make SQL query from table, - get last messages from all pairs of users with user ? as sender or recipient, and join them with users table to get names. I've managed to create something like this, but still want to ask if there is more simple
i want to fetch the photogrpher name, profile pic and last message of every user as we see in inbox..
table
user: profile pic, username,user_id
message: userid, photographerid, message, timestamp
Try this:
SELECT m.userid AS 'User id', u1.profile_pic AS 'User pic', u1.username AS 'User name`,
m.photographerid AS 'Photographer id', u2.profile_pic AS 'Photographer pic',
u2.username AS 'Photographer name`,
m.message, m.timestamp
FROM message m JOIN user u1 ON m.userid = u1.user_id
JOIN user u2 ON m.photographerid = u2.user_id
ORDER BY m.timestamp DESC LIMIT 1;
Update:
You can get latest messages for a user with the below query:
SELECT m.userid, a.photographerid, m.message, a.timestamp
FROM message m
JOIN (SELECT photographerid, MAX(timestamp) as timestamp
FROM message where userid = ?
GROUP BY photographerid
) a
ON m.photographerid = a.photographerid and m.timestamp = a.timestamp
WHERE m.userid = ?
UNION
SELECT a.userid, m.photographerid, m.message, a.timestamp
FROM message m
JOIN (SELECT userid, MAX(timestamp) as timestamp
FROM message where photographerid = ?
GROUP BY userid
) a
ON m.userid = a.userid and m.timestamp = a.timestamp
WHERE m.photographerid = ?
Once you get the message, you can JOIN the output of this query with user table to get the values of other columns, e.g.:
SELECT m.userid AS 'User id', u1.profile_pic AS 'User pic', u1.username AS 'User name`,
m.photographerid AS 'Photographer id', u2.profile_pic AS 'Photographer pic',
u2.username AS 'Photographer name`,
m.message, m.timestamp
FROM (
SELECT m.userid, a.photographerid, m.message, a.timestamp
FROM message m
JOIN (SELECT photographerid, MAX(timestamp) as timestamp
FROM message where userid = ?
GROUP BY photographerid
) a
ON m.photographerid = a.photographerid and m.timestamp = a.timestamp
WHERE m.userid = ?
UNION
SELECT a.userid, m.photographerid, m.message, a.timestamp
FROM message m
JOIN (SELECT userid, MAX(timestamp) as timestamp
FROM message where photographerid = ?
GROUP BY userid
) a
ON m.userid = a.userid and m.timestamp = a.timestamp
WHERE m.photographerid = ?
) m JOIN user u1 ON m.userid = u1.user_id
JOIN user u2 ON m.photographerid = u2.user_id;

Getting 2 same fields in the same time

I've 3 tables below. (sample)(mySql script)
customer
cust_id
cust_name
user_id
user_id_2
user
user_id
em_id
employee
em_id
em_name
How can I call the em_name field for user_id, and em_name field for user_id_2 by crossing user table in the same time with join??
Try this
SELECT q1.* ,
q2.em_name AS 'em_name_2'
FROM (SELECT c.cust_id ,
c.cust_name ,
c.user_id ,
c.user_id_2 ,
e.em_name
FROM dbo.customer AS c
INNER JOIN dbo.[user] AS u ON c.user_id = u.user_id
INNER JOIN dbo.employee AS e ON u.em_id = e.em_id
) q1
CROSS JOIN
( SELECT e.em_id ,
e.em_name
FROM dbo.customer AS c
INNER JOIN dbo.[user] AS u ON c.user_id_2 = u.user_id
INNER JOIN dbo.employee AS e ON u.em_id = e.em_id
) q2