Mysql group_concact what am i doing wrong - mysql

I am trying to get all favorite users of a particular user using this simple sub-query
select * from users u
where u.user_id in
(
select GROUP_CONCAT(f.favorite_id SEPARATOR ',') as favourites
from favourite_user f
where f.user_id in(14) group by user_id
)
When I run the subquery select GROUP_CONCAT(f.favorite_id SEPARATOR ',') as favourites
from favourite_user f
where f.user_id in(14) group by user_id it gives me result 6,8,11,10,13,15,7,12
and when i run this query select * from users u
where u.user_id in (6,8,11,10,13,15,7,12) it is returning 7 rows of result
But when i run the above mentioned main query it is just giving me the 1 row (the first one) instead of 7.
Can anyone explain me what am i doing wrong. I know this can also be done with joins but I'd like to know why this approach isn't working
Thank you in advance

You don't need GROUP_CONCAT(). Try
select *
from users
where user_id in
(
select favorite_id
from favourite_user
where user_id = 14
)
Here is SQLFiddle demo

Related

Find rank with query in MySql

I know that this question is asked also before but i tried all of them but no one works for me because my query is a little bit different because it has sum function in query that needs to get sum and in base of sum to get the rank of the user.
So my question is how to find the rank for single user my table is this:
currently i am trying with this query but this gives me all users.
SELECT u.user_name as userName
, sum(taken_quiz_points) as totalPoints
FROM taken_quiz as q
, users_app as u
WHERE q.taken_quiz_user_id = u.user_id
GROUP
BY taken_quiz_user_id
ORDER
BY totalPoints DESC
First of all, you should use INNER JOIN when you query data from multiple tables.
Also, I don't think it's possible to ORDER BY an alias, you have to repeat the operation of the alias.
If you want to have the rank of a single user you have to add a WHERE condition, like WHERE u.name = "toto" or something.
You should end up with this :
SELECT
u.user_name as userName ,
sum(q.taken_quiz_points) as totalPoints
FROM taken_quiz q
INNER JOIN users_app u ON q.taken_quiz_user_id = u.user_id
WHERE u.name = "toto"
GROUP BY q.taken_quiz_user_id
ORDER BY sum(q.taken_quiz_points) DESC
So you need the whole dataset in order to know the ranking of the person. It's a bit ugly, but you can nest to get the ranking, and then select from the ranked dataset the person you are interested in:-
Select userName, user_rank from
(Select userName,totalpoints ,dense_rank() OVER (Order by totalpoints desc) as user_rank
from (
SELECT u.user_name as userName ,sum(taken_quiz_points) as totalPoints
FROM taken_quiz as q, users_app as u
WHERE q.taken_quiz_user_id=u.user_id GROUP BY user_name,
taken_quiz_user_id) aa
) bb
where userName ='bob'

MYSQL COUNT with SELECT condition

Im newbie please help me on my project. I have 2 tables below.
Table user:
Table Likes
I want to count all likes per story_id and check if the given user has like the story else it will return null.
as of now this is my query and output, given user id = 1.
SELECT COUNT(*) , sl.story_id, u.id as user
FROM stories_likes sl
LEFT JOIN users u ON sl.user_id = u.id AND sl.user_id = 1
GROUP BY sl.story_id
My output:
But what i want to get output is:
Given: user_id = 1
Given user_id = 4
Sorry for the construction of my question i dont know how. Thanks in advance
If the query should display the result for a one particular user_id only then try the following query:
select count(*),
story_id,
(case find_in_set(1, Group_concat(user_id separator ',')) >0 then 1
else NULL
end
)as user_id
from Stories_Likes
group by story_id;
In above query, you can put user_id manually after when, or you can set a variable with particular Id and use it in the query.
For i.e., if you want to check for user_id=4, then put 4 after when and then.
Click here for the Updated Demo
Hope it helps!
The users table is left joined to the query, so it may have null values. Instead, you should use the user_id column from the stories_likes table:
SELECT COUNT(*) , sl.story_id, sl.user_id as user
-- Here --------------------------^
FROM stories_likes sl
LEFT JOIN users u ON sl.user_id = u.id AND sl.user_id = 1
GROUP BY sl.story_id
Got the answer. for those who has the same problem and needed this here's the answer.
SELECT COUNT(*) , sl.story_id, t.user_id
FROM stories_likes sl
LEFT JOIN users u ON sl.user_id = u.id
LEFT JOIN (SELECT * FROM stories_likes WHERE user_id = 4) t ON
sl.story_id = t.story_id
GROUP BY sl.story_id
Where the given user is declared on temporary table t

How to pass parent field in sub union query

I've this query and its giving an error that unknown U.UserID column in where clause but I can't see any error in it as my Users table instance is U
SELECT GROUP_CONCAT(U.UserID),
(
SELECT COUNT(DISTINCT(UserID))
FROM (
SELECT FriendID as UserID
FROM Friends
WHERE UserID=U.UserID AND Status=1
UNION All
SELECT UserID
FROM Follow
WHERE Type='user' AND TypeEntityID=U.UserID
) tbl
) as NoOfFriendsFollow
FROM `Users` `U`
WHERE `U`.`UserID` IN('1')
LIMIT 10
Any solution for this query or let me know where I'm wrong
SELECT GROUP_CONCAT(UserID),
(
SELECT COUNT(DISTINCT(UserID)) FROM
(
SELECT FriendID as UserID FROM Friends F
INNER JOIN Users U ON U.UserID=F.FriendID
WHERE F.Status=1
UNION All
SELECT FF.UserID FROM Follow FF
INNER JOIN Users U ON U.UserID=FF.UserID
WHERE Type='user' AND TypeEntityID=U.UserID
) tbl
) as NoOfFriendsFollow
FROM Users WHERE UserID IN('1') LIMIT 10;
Just try above code.
Hope this will helps.
Unfortunately, MySSQL does not permit you to use an outer table reference "two levels down". So you can do:
SELECT U.UserID,
(SELECT COUNT(DISTINCT UserID)
FROM (SELECT fr.FriendID as UserID, fr.FriendId as compareId
FROM Friends fr
WHERE fr.Status = 1
UNION All
SELECT f.UserID, f.TypeEntityID as compareId
FROM Follow f
WHERE f.Type = 'user'
) tbl
WHERE tbl.UserID = compareId
) as NoOfFriendsFollow
FROM Users U
WHERE U.UserID IN (1)
LIMIT 10;
Notes:
This moves the comparison into the middle subquery, so the query parses.
Presumably UserId is an integer. Only use single quotes for string and date constants.
The GROUP_CONCAT() doesn't make sense. It turns the query into an aggregation query that returns only one row.
I double the LIMIT is needed either. There should be one row per UserId.
Always use qualified column names when you have multiple tables in a query.

SQL query to exclude one to many that have a specific value?

Using MySQL, I'd like to list all users that don't have the document "liaison". It could means Users that does not have any document at all, or users that have documents, but not "liaison" in these ones.
How can I do using MySQL Query ? I can't make it work!
Here's the (simple) model
Users (id, name)
Documents (id, user_id, name, path)
The NOT EXISTS is a workable solution. As an alternative, sometimes, with large sets, an "anti JOIN" operation can give better performance:
SELECT u.*
FROM Users u
LEFT
JOIN (SELECT d.user_id
FROM Documents d
WHERE d.name = 'liaison'
) l
ON l.user_id = u.id
WHERE l.user_id IS NULL
The inline view aliased as l returns us a list of user_id that have document named 'liaison'; that result set gets outer joined to the Users table, and then we exclude any rows where we found a match (the test of l.user_id IS NULL).
This returns a resultset equivalent to your query with the NOT EXISTS predicate.
Another alternative is to use a query with a NOT IN predicate. Note that we need to guarantee that the subquery does not return a NULL, so the general approach is to include an IS NOT NULL predicate on the column being returned by the subquery.
SELECT u.*
FROM Users u
WHERE u.id NOT IN
( SELECT d.user_id
FROM Documents d
WHERE d.user_id IS NOT NULL
AND d.name = 'liaison'
)
I'd write the NOT EXISTS query like this:
SELECT u.*
FROM Users u
WHERE NOT EXISTS
( SELECT 1
FROM Documents d
WHERE d.name = 'liaison'
AND d.user_id = u.id
)
My personal preference is to use a literal 1 in the SELECT list of that correlated subquery; it reminds me that the query is just looking for the existence of 1 row.)
Again, I usually find that the "anti-join" pattern gives the best performance with large sets. (You'd need to look at the EXPLAIN output for each statement, and measure the performance of each to determine which will work best in your situation.)
The correct query you are looking for is:
SELECT
*
FROM
Users
WHERE
id NOT IN (
SELECT
user_id
FROM
Documents
WHERE
name = "liaison"
)
This will achieve the exact result you are looking for. If a specific user has no documents, it will be listed. If it has many documents, and one of those is 'liaison', it won't be listed.
If you want to search for 'liaison' in your document's name, replace name = "liaison" for name LIKE "%liaison%".
It basically says: Select all users such as there are no documents with name "liaison" pointing to it.
So, I finally came up with this solution that seems to work good :
SELECT * FROM users u WHERE id NOT IN (SELECT DISTINCT user_id FROM user_documents WHERE name = 'LIAISON') ORDER BY c.lastname, c.firstname
SELECT users.*
FROM users left join Documents
on users.id = Documents.user_id
and documents.name='LIAISON'
WHERE documents.user_id is null
select * from Users where not exists (select id from Documents where Users.id = Documents.id and Documents.name = 'liaison')
Try :
SELECT DISTINCT u.*
FROM users u LEFT JOIN documents d ON d.user_id = u.id
WHERE d.id IS NULL OR d.name NOT LIKE '%liaison%'
Remove percent signs if "liaison" is the exact name of the document.

Stacked SQL Query error and complications

I just learned you can stack SQL queries instead of running 4 different ones and combining the data. So I'm read tutorials and stuff but still can't figure this certain one out.
SELECT ID,
(SELECT firstname
FROM user
WHERE ID = fundraiser.user_ID) AS firstname,
(SELECT lastname
FROM user
WHERE ID = fundraiser.user_ID) AS lastname,
(SELECT org_fund_id
FROM fundraiser
WHERE ID = fundraiser.ID) AS org_fund_ID,
(SELECT ref_ID
FROM fundraiser
WHERE ID = fundraiser.ID) AS ref_ID
FROM fundraiser
WHERE 1
ORDER BY org_fund_ID ASC
Here's the basic setup for the database/tables being called:
[fundraiser] - (ID, ref_ID, user_ID, org_fund_ID) and
[user] - (firstname, lastname)
Basically, I want to pull all of the fields from "fundraiser" from the database but get the corresponding "user.firstname" and "user.lastname" where "fundraiser.user_ID" = "user.ID".
So it would come out something like this as a row:
fundraiser.ID, fundraiser.user_ID, fundraiser.ref_ID, user.firstname, user.lastname
I've tried like 30 different ways of writing this query and all have failed. The error I get is "#1242 - Subquery returns more than 1 row".
Not sure how I can give you more information so you can visualize what I'm talking about, but I will provide whatever data I can.
Thanks in advance.
to select ALL columns:
SELECT *
FROM fundraiser f
INNER JOIN user u
ON u.ID = f.user_ID
ORDER BY f.ord_fund_id ASC;
to select needed columns:
SELECT
u.firstname,
u.lastname,
f.org_fund_id,
f.ref_ID
FROM fundraiser f
INNER JOIN user u ON u.ID = f.user_ID
ORDER BY f.ord_fund_id ASC;
this should be, what you need. See this Wikipedia page.