Combining select queries - mysql

I am working with a MySQL database. I am suppose to combine three select queries, to "improve performance". Each select below is dependent on the previous ID retrieved.
So far, I've tried the following...
# multiple select from tables
select user.name, group.ID
from user as u, group as g
where u.name = <name_here>
# inner join...
select user.ID, group.ID,
from user
inner join group
on user.ID = group.ID
I need to select the user.name and group.ID based on a username param. Is there a way to query this data in a single statement?

I don't know if I understand your need, lets try:
Try to use this query:
select pGroupMatch.GroupID, ProfileData.ID
from pUserMatch
inner join pGroupMatch on pGroupMatch.GroupID = pUserMatch.GroupID
inner join ProfileData on ProfileData.id = pGroupMatch.ProfileID
where pUserMatch.username = "<username>";
Check if you can create indexes for improve your query, if you can try it:
CREATE INDEX idx_pUserMatch_01 ON pUserMatch (GroupID);
CREATE INDEX idx_pGroupMatch_01 ON pGroupMatch (ProfileID);

Please use join for your requirement. Please try below query
select t3.* from Profiles.pUserMatch t1
left join Profiles.pGroupMatch t2 ON t2.GroupID=t1.GroupID
left join Profiles.ProfileData t3 ON t3.ID=t2.ProfileID
where t1.username = "<username>";
I hope above query will help you.Please feel free to comment. Thanks.

This is the query you get by joining the tree queries you already have:
SELECT pd.*
FROM Profiles.ProfileData pd
# ... where ID = "<profile_id>", profile_id = select ProfileID from ...
INNER JOIN Profiles.pGroupMatch pm ON pd.ID = pm.ProfileID
# ... where GroupID = "<group_id>", group_id = select GroupID from ...
INNER JOIN Profiles.pUserMatch pu ON pm.GroupID = pm.GroupID
WHERE pm.username = "<username>"
I put in comments the fragments of your queries that gets converted to JOIN subclauses.
Read more about the syntax of the JOIN subclause of the SELECT statement.

You don't need foreign keys to join stuff:
select p.* from Profiles.pUserMatch u
join Profile.pGroupMatch g on u.GroupID = g.GroupID
join Profile.ProfileData p on g.ProfileID = p.ID
where u.username = ?

Related

SQL Merge Two SELECT statements together

I have the following SQL query which returns 2 results which are the same only different by a where clause.
I would like to have them combined and group them under the user names. At the moment the two results are displayed but the results are not fully combined and the users are shown twice because of the two select statements.
How can I combine the two to create a single result.
The SQL query is as follows
SELECT
COUNT (asings.user_id),
post_status.status_id as status_id,
users.name,
users.id as user_id
from asigns
LEFT JOIN
post_status on asigns.post_id = post_status.post_id
RIGHT JOIN
users on asigns.user_id = users.id
WHERE
post_status.status_id = 2
GROUP BY users.id
UNION
SELECT
COUNT(asigns.user_id),
post_status.status_id as status_id,
users.name,
users.id from asigns
LEFT JOIN
post_status on asigns.post_id = post_status.post_id
RIGHT JOIN
users on asigns.user_id = users.id
WHERE
post_status.status_id = 3
GROUP BY users.id
See in this photo the usernames are appearing twice, what I want is to join the two username, and move count as two different columns depending on the status_id
How can I solve this. Thanks
You should use a single query with conditional aggregation:
SELECT
SUM(ps.status_id = 2) AS cnt_2,
SUM(ps.status_id = 3) AS cnt_3,
u.name,
u.id as user_id
FROM users u
LEFT JOIN assigns a ON a.user_id = u.id
LEFT JOIN post_status ps ON a.post_id = ps.post_id
GROUP BY u.id;
Use SELECT distinct for the union:
SELECT distinct * FROM ([FIRST SELECT] UNION [SECOND SELECT])
Or GROUP BY username
SELECT * FROM ([FIRST SELECT] UNION [SECOND SELECT]) GROUP BY username
BUT I suggest to review your both selects, if it differs just in the where clause so use where clause with the operator OR and you handle it just by one SELECT
Although your are using a LEFT and a RIGHT join and implicitly an INNER join between users and asigns, the WHERE clause transforms all the joins to INNER joins, because you are picking only the matching rows from post_status.
So, you only need INNER joins and conditional aggregation:
SELECT COALESCE(SUM(ps.status_id = 2), 0) counter_2,
COALESCE(SUM(ps.status_id = 3), 0) counter_3,
u.name,
u.id AS user_id
FROM users u
INNER JOIN asigns a ON a.user_id = u.id
INNER JOIN post_status ps ON ps.post_id = a.post_id
WHERE ps.status_id IN (2, 3)
GROUP BY u.id;

Mysql query to proper Laravel $query

I have this logic query that doesn't work because I need to Join like 4 different tables, which is insane but please help me out, I will find a better way in the future.
select * from approvals
where approvable_type =
(select model from permission_configs
where variable = (
select permission_slug from role_permission
where role_id = (
select role_id from role_user
where user_id = approvals.user_id) ) )
Please give me the above query in Eloquent with multiple join! I will forever be grateful to you.
You could refactor your query using inner join instead of where and subquery
select *
from approvals a
INNER JOIN permission_configs p ON a.approvable_type = p.model
INNER JOIN role_permission r ON p.variable = r.permission_slug
INNER JOIN role_user u ON r.role_id = u.role_id
WHERE u.user_id = a.user_id
once done, you could take a look at Eloquent for join

MYSQL: Using a join after and AND

the MYSQL query below combines a number of tables. However, as you can see, I would like to add a LEFT JOIN at the end on the receipt table. The query returns an error when I add the LEFT JOIN. Anybody know the best way to LEFT JOIN the receipt table to the rest of the query. Sorry if this is a newbie question. Thanks !!
SELECT user_name, expense_category, merchant_name, expense_cost, expense_date, expense_status, receipt_image, expense_comment
FROM users, expenses, merchants, receipts
WHERE ".$adminId." = expenses.admin_id
AND expenses.user_id = users.user_id
AND expenses.merchant_id = merchants.merchant_id
AND LEFT JOIN (receipts)
ON expenses.receipt_id = receipts.receipt_id
Here is a clean approach of doing it, note that I have added alias for the tables for better readability so you may use the alias name in the select statement to fetch the column from the proper table.
SELECT
u.user_name,
ex.expense_category,
mer.merchant_name,
ex.expense_cost,
ex.expense_date,
ex.expense_status,
re.receipt_image,
ex.expense_comment
FROM users u
JOIN expenses ex on ex.user_id = u.user_id
JOIN merchants mer on mer.merchant_id = ex.merchant_id
LEFT JOIN receipts re on re.receipt_id = ex.receipt_id
where
ex.admin_id = '$adminId'
Try this,
SELECT user_name, expense_category, merchant_name, expense_cost, expense_date, expense_status, receipt_image, expense_comment
FROM users, expenses, merchants, receipts
LEFT JOIN receipts ON expenses.receipt_id = receipts.receipt_id
WHERE ".$adminId." = expenses.admin_id
AND expenses.user_id = users.user_id
AND expenses.merchant_id = merchants.merchant_id
Use join clauses instead of where clause. I.e.
SELECT user_name, expense_category, merchant_name, expense_cost, expense_date, expense_status, receipt_image, expense_comment
FROM users
INNER JOIN expenses on users.user_id = expenses.expenses_id
INNER JOIN merchants on merchants.merchant_id = expenses.merchant_id
LEFT JOIN (receipts)
ON expenses.receipt_id = receipts.receipt_id
WHERE ".$adminId." = expenses.admin_id
Note that any columns from the receipts will be NULL in the select statement whenever there's no matching record.

Select Query based on values in result set

Is there anyway to select all from 1 table based on the result of one query which contains multiple values without having to do 2 separate queries?
Say long join query will produce a list of id's
SELECT xyz FROM table long join query WHERE id = array of ids found in result table
added example:
SELECT * FROM tweets as t
where t.user_id
in(
SELECT uff.id, uff.username
FROM users as uf
LEFT JOIN followlinks as fl
ON uf.id = fl.user_id
LEFT JOIN users as uff
ON fl.follow_id = uff.id
WHERE uff.id = 1
)
The bit in the parenthesis returns an id and user name of who the user is following (uff.id=1)
How do i then get all 'tweets' by all the id's in the generated resultset
You can use subquery:
SELECT * FROM `table1` WHERE `id` IN (SELECT `table2`.id FROM `table2` )
You might want to check documentation for syntax
SELECT xyz FROM table_A join table_B WHERE table_A.id IN (SELECT ID FROM table_C);
I think you mean something like
edited after the OP edit
SELECT * FROM tweets as t
WHERE t.user_id
in(
SELECT uff.id //remove the second field, you just need the id
FROM users as uf
LEFT JOIN followlinks as fl
ON uf.id = fl.user_id
LEFT JOIN users as uff
ON fl.follow_id = uff.id
WHERE uff.id = 1
)
After trying the in clause I coudnt get the results I was after but after rethinking what I was trying to do I got my results with an additional join clause
SELECT uff.username, t.content
FROM users as uf
JOIN followlinks as fl
ON uf.id = fl.user_id
JOIN users as uff
ON fl.follow_id = uff.id
JOIN tweets as t
ON t.user_id = uff.id
WHERE uf.id = 1

Mysql Nested/Multiple Query handling

I have three queries gives me result individually correct but my requirement is i need all result in single query only so how should i proceed?
select * from user_post_like
inner join user_post on user_post_like.postID = user_post.postID
inner join Users on Users.userID=user_post_like.userID
where (user_post.poster='$uid' AND user_post_like.userID!='$uid')
ORDER BY likeID DESC;
select * from user_post_comment
inner join user_post on user_post_comment.postID = user_post.postID
inner join Users on Users.userID=user_post_comment.commenter
where (user_post.poster='$uid' AND user_post_comment.commenter!='$uid')
ORDER BY commentID DESC;
select * from user_post_share
inner join user_post on user_post_share.postID = user_post.postID
inner join Users on Users.userID=user_post_share.Share_user_id
where (user_post.poster='$uid' AND user_post_share.Share_user_id!='$uid')
ORDER BY shareID DESC;
Since you're joining the tables anyway, you can put columns from all in your select - and keep your statement readable. If you have duplicate column names (from different tables) you may need to aggregate them with functions and group by.
SELECT s.*, p.*, u.*
FROM user_post_share s
INNER JOIN user_post p ON s.postID = p.postID
INNER JOIN Users u ON u.userID = p.poster
WHERE (p.poster='$uid' AND s.Share_user_id != '$uid')
ORDER BY shareID DESC
try sumthing like this
select * from user_post_like,user_post_comment,user_post_share <inner joins> <where conditions>