How to pass parent field in sub union query - mysql

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.

Related

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

SQL intermediate table having column = max(column)

I have 2 tables: user and review, a one-to-many relationship.
When I execute the following query:
SELECT
user_id,
count(*) totalReviews,
USER . NAME
FROM
review,
USER
WHERE
USER .id = review.user_id
GROUP BY
user_id
I get:
1 2 marius
2 2 daniela
3 1 alin
What I want to do now is to display first 2 users because they have given the most reviews(2).
I tried adding having, if I hardcode having totalReviews=2 it works, but if I write having total = max(total) I get 0 results, while if I'm trying with,
SELECT
*
FROM
(
SELECT
user_id,
count(*) total,
USER . NAME
FROM
review,
USER
WHERE
USER .id = review.user_id
GROUP BY
user_id
) A
WHERE
total = (SELECT max(total) FROM A) `
I get an error (table A doesn't exist)
You would do this with ORDER BY and LIMIT:
SELECT u.id, count(*) as totalReviews, u.name
FROM review r JOIN
user u
ON u.id = r.user_id
GROUP BY u.id, u.name
ORDER BY totalReviews DESC
LIMIT 2;
Notes:
Never use commas in the FROM clause. Always use proper, explicit JOIN syntax.
Table aliases make the query easier to write and read.
EDIT:
If occurs to me that you want all users with the maximum number of reviews, not exactly 2. Here is one method:
SELECT u.id, COUNT(*) as totalReviews, u.name
FROM review r JOIN
user u
ON u.id = r.user_id
GROUP BY u.id, u.name
HAVING totalReviews = (SELECT COUNT(*)
FROM review r2
GROUP BY r2.user_id
ORDER BY COUNT(*) DESC
LIMIT 1
);
Note that the subquery in the HAVING clause is simpler than the outer query. There is no need to bring in the user name.

How to achiave this:MYSQL SELECT if true select a else select b?

I want to select user.* if chat.chat_type IS NULL, but if chat.chat_type = 1
I want to select group.*
SELECT
CASE
WHEN chat.chat_type IS NULL THEN user.*
WHEN chat.chat_type =1 THEN group.*
END,
x,y
FROM `chat` LEFT JOIN group ...
How I can achieve this?
The database design as described is not so good, because you have an ID in your chat table that can either be a user ID or a group ID. Thus you cannot have a constraint (foreign key) on this column, which makes it possible to put any value in there, i.e. even an ID that doesn't exist.
Anyway, with the design given, to get either user or group you outer join both tables on the conditions you already mentioned. Then use COALESCE to see whether you got a user or a group in the result row.
select c.from, coalesce(u.name, g.name) as to_name
from chat c
left join usr u on c.chat_type is null and c.to = u.user_id
left join grp g on c.chat_type = 1 and c.to = g.group_id
where c.chat_type is null or c.chat_type = 1;
You have to use Union:
SELECT user.* from user join ... where chat.chat_type is null
Union
SELECT `Group`.* from `Group` join .... where chat.chat_type =1
if user and Group have a different number of column, you have to use a Default where you have less columns.
Hint: because Group is a Keyword, you should rename your table

MySQL subquery referencing a table outside it's scope

In the following query I'm receiving
Error Code: 1054 Unknown column 'PRF.user_id' in 'where clause'
This is due to the fact that the subquery is attempting to reference PRF.user_id which is outside it's own scope. How can I rewrite the query in order to overcome this issue?
SELECT user_id, lastname,
(
SELECT COUNT(*) FROM
(
SELECT *
FROM Demo_Orders_M
WHERE DemoOrderStatus = 253
AND DemoOrderDate BETWEEN '2015-06-19' AND '2015-06-26'
AND `User` = PRF.user_id
GROUP BY CustomerID, `User`
HAVING COUNT(*) > 1
) t1
) recycling
FROM tbl_profiles PRF
JOIN tbl_users U ON PRF.user_id = U.id
WHERE PRF.user_id IN ( SELECT a.user_id FROM tbl_profiles a WHERE a.user_id IN ('1210', '789') )
GROUP BY user_id
The first thing I've noticed is that your subquery has a GROUP BY and HAVING clause without any aggregate functions, which shouldn't be the case. It looks to me that what you are trying to accomplish is getting the COUNT(*) of demo orders for each user/customer combination. You can write that individual query like this:
SELECT customerID, user, COUNT(*) AS numOrders
FROM demo_orders_m
WHERE demoOrderStatus = 253 AND demoOrderDate BETWEEN '2015-06-19' AND '2015-06-26'
GROUP BY customerID, user
HAVING COUNT(*) > 1;
This is a simple aggregation query that will pull the number of orders each user has that meet the given criteria, and as long as they have two or more orders.
Then, you can join these results to your users table to get other info about those users. One thing to note about your query also is that you don't need to write an extra select statement that pulls the user ids like that, what you've written is redundant. The whole condition can be rewritten as:
WHERE PRF.user_id IN(1210, 789)
So, the final query would be as follows. Note that I used a LEFT JOIN and the coalesce function to make sure a zero value is returned for users who didn't meet the order criteria, and as a result were not returned by the subquery:
SELECT user_id, lastname, COALESCE(numOrders, 0) AS numOrders
FROM tbl_profiles PRF
JOIN tbl_users U ON U.id = PRF.user_id
LEFT JOIN(
SELECT customerID, user, COUNT(*) AS numOrders
FROM demo_orders_m
WHERE demoOrderStatus = 253 AND demoOrderDate BETWEEN '2015-06-19' AND '2015-06-26'
GROUP BY customerID, user
HAVING COUNT(*) > 1) TMP ON TMP.user = U.id AND TMP.user IN (1210, 789);

Sql statement with expression in group by

I have a question about one sql statement for my mysql db. I have a table with the following columns :-
sender_id | receiver_id | content | dateAndTime
As you understand I would like to implement sending messages between users. I want to select the last message(doesn't matter sent or received) with every user. Something like the messages in facebook. I guess that I should use expression in group by if it is possible but I would like to see your opinion how I should do it. Thanks!
For This kind of purpose, your field dateAndTime is must be date-time type.
SELECT * FROM TABLE ORDER BY dateAndTime DESC
You can retrieve latest data using this descending order.
Try this one
SELECT C.ID, T.content, T.dateAndTime FROM T JOIN
(
SELECT ID, MAX(dateAndTime) 'last' FROM
(
SELECT sender_id 'ID', content, dateAndTime FROM T
UNION
SELECT receiver_id 'ID', content, dateAndTime FROM T
) B
GROUP BY ID
) C
WHERE T.dateAndTime = C.last AND (T.sender_id = C.ID OR T.receiver_id = C.ID)
Assuming you have a 'users' table, and your stated table named 'mytable' you could:
select users.id,mytable.content, MAX(mytable.dateAndTime) as date
from users join mytable
on users.id = mytable.sender_id
or users.id = mytable.receiver_id
group by users.id, mytable.content, date
The max function will keep only the latest date from each group generated by the group by
EDIT: try this instead
select users.id, mytable.content, mytable.dateAndTime
from users join mytable
on users.id = mytable.sender_id
or users.id = mytable.receiver_id
where mytable.dateAndTime = (select max(t.dateAndTime) from mytable as t where t.receiver_id = users.id or t.sender_id = users.id)