Select users from table foreach repeated id - mysql

I have this table:
users
id | name
---------------------
1 | Lisa
2 | John
and i have this users list:
(1,2,2,2,1,2)
and i want to get this result:
Lisa,John,John,John,Lisa,John
how i can get this result just using SQL query in my Phpmyadmin without using PHP?
i must use Left Join ?

(Assuming orders table is on the same server) You should use inner join here. Because, there should be an user to have an entry in orders table.
SELECT abc = STUFF(( Select user.user_name + ',' from
orders inner join users on users.id = orders.user_id where orders.user_id in (your string of user ids) for
xml_path(' ')), 1, 1, '') FROM temp1

Related

How to get all Users and its orders as a sub-set in mysql

I Have a table like
user.id
user.firstname
user.lastname
another table I have is
order.id
order.userid
order.name
order.price
with this query:
SELECT user.firstname, user.lastname, order.name
FROM Customers
LEFT JOIN Orders ON user.id = order.userid;
If I have 3 users and each user have 3 order, I get 9 rows in results.
how can I get the 3 rows having subsets of 3 order objects in them.
Here is an example of output I need
firstname | lastname | onderNames
im | ah | book, pen, watch
abc. | dff. | rice, wheat
thanks in advance
You are looking for an aggregation query. The most common structure is:
SELECT c.firstname, c.lastname, GROUP_CONCAT(o.name SEPARTOR ', ') as names
FROM Customers c LEFT JOIN
Orders o
ON c.id = o.userid
GROUP BY c.id, c.firstname, c.lastname;
This puts the result in a string. You can also put the result in JSON -- which is also a string but formatted as a JSON array -- using JSON_ARRAYAGG().

Selecting a count of rows having a max value

Working example: http://sqlfiddle.com/#!9/80995/20
I have three tables, a user table, a user_group table, and a link table.
The link table contains the dates that users were added to user groups. I need a query that returns the count of users currently in each group. The most recent date determines the group that the user is currently in.
SELECT
user_groups.name,
COUNT(l.name) AS ct,
GROUP_CONCAT(l.`name` separator ", ") AS members
FROM user_groups
LEFT JOIN
(SELECT MAX(added), group_id, name FROM link LEFT JOIN users ON users.id = link.user_id GROUP BY user_id) l
ON l.group_id = user_groups.id
GROUP BY user_groups.id
My question is if the query I have written could be optimized, or written better.
Thanks!
Ben
You actual query is not giving you the answer you want; at least, as far as I understand your question. John actually joined group 2 on 2017-01-05, yet it appears on group 1 (that he joined on 2017-01-01) on your results. Note also you're missing one Group 4.
Using standard SQL, I think the next query is what you're looking for. The comments in the query should clarify what each part is doing:
SELECT
user_groups.name AS group_name,
COUNT(u.name) AS member_count,
group_concat(u.name separator ', ') AS members
FROM
user_groups
LEFT JOIN
(
SELECT * FROM
(-- For each user, find most recent date s/he got into a group
SELECT
user_id AS the_user_id, MAX(added) AS last_added
FROM
link
GROUP BY
the_user_id
) AS u_a
-- Join back to the link table, so that the `group_id` can be retrieved
JOIN link l2 ON l2.user_id = u_a.the_user_id AND l2.added = u_a.last_added
) AS most_recent_group ON most_recent_group.group_id = user_groups.id
-- And get the users...
LEFT JOIN users u ON u.id = most_recent_group.the_user_id
GROUP BY
user_groups.id, user_groups.name
ORDER BY
user_groups.name ;
This can be written in a more compact way in MySQL (abusing the fact that, in older versions of MySQL, it doesn't follow the SQL standard for the GROUP BY restrictions).
That's what you'll get:
group_name | member_count | members
:--------- | -----------: | :-------------
Group 1 | 2 | Mikie, Dominic
Group 2 | 2 | John, Paddy
Group 3 | 0 | null
Group 4 | 1 | Nellie
dbfiddle here
Note that this query can be simplified if you use a database with window functions (such as MariaDB 10.2). Then, you can use:
SELECT
user_groups.name AS group_name,
COUNT(u.name) AS member_count,
group_concat(u.name separator ', ') AS members
FROM
user_groups
LEFT JOIN
(
SELECT
user_id AS the_user_id,
last_value(group_id) OVER (PARTITION BY user_id ORDER BY added) AS group_id
FROM
link
GROUP BY
user_id
) AS most_recent_group ON most_recent_group.group_id = user_groups.id
-- And get the users...
LEFT JOIN users u ON u.id = most_recent_group.the_user_id
GROUP BY
user_groups.id, user_groups.name
ORDER BY
user_groups.name ;
dbfiddle here

SQL retrieve joined data an array

I have the following database structure:
users:
id
name
user_activities:
user_id
activity_id
activities:
id
name
I'm trying to write a Select query that will output the following:
- user1.id, activities: {[activity.id, activity.name], ['activity.id, activity.name]};
- user2.id, activities: {[activity.id, activity.name], ['activity.id, activity.name]};
I know how to do it in two steps, but I have many users and selecting activities for each one is heavy. Is there way to do it with one MySQL query?
Solution using GROUP_CONCAT function with SEPARATOR option, which lets you get all activities for a certain user:
SELECT u.id, GROUP_CONCAT( a.id, "|", a.name
SEPARATOR ', ' ) AS useractivities
FROM `users` u
INNER JOIN `user_activities` ua ON u.id = ua.user_id
INNER JOIN `activities` a ON a.id = ua.activity_id
GROUP BY u.id
This query will return a resultset in such state:
id | useractivities
------------------------------------
79 | 17|sport
18 | 3|music, 19|outing, 17|sport
.. | ....
Then, while fetching each row from resultset you can easily explode(split) the useractivities field value by comma(as delimiter) and thus, get all activities for a certain user

SQL SELECT name by id

I need help with a sql query.
I have these 2 tables:
player_locations:
ID | playerid | location <- unqiue key
---|-----------------------
1 | 1 | DOWNTOWN
and users:
ID | playername | [..]
----|--------------------
1 | example1 | ...
I need a select to get the users.playername from the player_locations.playerid. I have the unique location to get the player_locations.playerid.
Pseudo query:
SELECT playername
FROM users
WHERE id = player_locations.playerid
AND player_locations.location = "DOWNTOWN";
The output should be example1.
This is just a simple INNER JOIN. The general syntax for a JOIN is:
SELECT stuff
FROM table1
JOIN table2 ON table1.relatedColumn = table2.relatedColumn
In your case, you can relate the two tables using the id column from users and playerid column from player_locations. You can also include your 'DOWNTOWN' requirement in the JOIN statement. Try this:
SELECT u.playername
FROM users u
JOIN player_locations pl ON pl.playerid = u.id AND pl.location = 'DOWNTOWN';
EDIT
While I personally prefer the above syntax, I would like you to be aware of another way to write this which is similar to what you have now.
You can also select from multiple tables by using a comma in your FROM clause to separate them. Then, in your WHERE clause you can insert your conditions:
SELECT u.playername
FROM users u, player_locations pl
WHERE u.id = pl.playerid AND pl.location = 'DOWNTOWN';
Here is the solution.
SELECT
playername
FROM users
WHERE id = (SELECT id FROM player_locations WHERE location='DOWNTOWN')
I have a idea, try this:
SELECT playername
FROM users
WHERE id IN (SELECT DISTINCT playerid FROM player_location WHERE location LIKE "DOWNTOWN");

MySQL chat table, join user names?

I have a simple chat database like this:
id | from | to | message
---|------|----|-----------------
1 | 1 | 2 | hello
2 | 1 | 2 | are you there?
3 | 2 | 1 | yes I'm here!
Also there is a second table that holds the names
`users`.`firstname` and `users`.`lastname`
I'm trying to combine the two, so when retrieving the chats, I'd also have the names of both participants. My query looks like this right now:
SELECT
`messages`.*,
CONCAT(`users`.`firstname`, " ", `users`.`lastname`) as `nameFrom`
FROM `messages`
INNER JOIN
`users` ON `messages`.`from` = `users`.`id`
It works fine, but if I try to add another join, just change messages.from to messages.to I get errors.
How do I combine the first name & last name of each participant when retrieving the chat log?
Thanks
Looks like you're trying to get both the sender and receiver? If so, this should work joining the Users table twice:
SELECT
`messages`.*,
CONCAT(u.`firstname`, " ", u.`lastname`) as `nameFrom`,
CONCAT(u2.`firstname`, " ", u2.`lastname`) as `nameTo`
FROM `messages`
INNER JOIN
`users` u ON `messages`.`from` = u.`id`
INNER JOIN
`users` u2 ON `messages`.`to` = u2.`id`
You need to basically join the table users twice on table messages provided that you supply an ALIAS to uniquely identify the tables with the same table name.
SELECT messages.*,
CONCAT(a.firstname, ' ', a.lastname) as nameFrom,
CONCAT(b.firstname, ' ', b.lastname) as nameTo
FROM messages
INNER JOIN users a
ON messages.from = a.id
INNER JOIN users b
ON messages.to = b.id
SQLFiddle Demo