Need to concatenate results of a subquery in a select statement - mysql

I have three tables
Table1: Users
Columns: User_ID (int), FirstName, LastName....
Values
1 Jane Doe
2 John Doe
3 Mike Smith
Table2: User_Groups
Columns: User_ID (int), Group_ID(int)
Values:
Row1: 1 2
Row2: 1 3
Row3: 2 1
Row4: 2 3
Row5: 3 1
Table3: Groups
Columns: Group_ID (int), GroupName(varchar)
Values
Row1: 1 Admin
Row2: 2 Power User
Row3: 3 Developer
I would like to create a query that can return the results in the following way:
**RESULT
UserID GroupNames
Row1: 1 Power User, Developer
Row2: 2 Admin, Developer
Row3: 3 Admin
In SQL Server - I was able to achieve it using something like this:
SELECT User_ID,
SUBSTRING(
replace(
replace(
(SELECT Groups.GroupName
FROM User_Groups, Groups
where groups.Group_ID =
User_Groups.Group_ID AND
User_Groups.User_ID =Users.User_ID
FOR XML PATH('') )
,'<GROUPNAME>',', ')
,'</GROUPNAME>',''),3,2000) as UserGroups
FROM User_Groups LEFT JOIN Groups ON
User_Groups.Group_ID=Groups.Group_ID
ORDER BY User_ID ASC
I wanted to do get a similar final result in MySQL (tried GROUP_CONCAT etc) but unsuccessful.. how can I get similar **RESULT in MySQL. Please note the tables exist already and I cant change them.
Any help will be greatly appreciated

This works:
SELECT
t1.User_ID AS UserID,
(
SELECT
GROUP_CONCAT(t2.GroupName)
FROM
Groups t2
WHERE
t2.Group_ID IN(
SELECT
t3.Group_ID
FROM
User_Groups t3
WHERE
t3.iUser_ID = t1.User_ID
)
) AS GroupNames
FROM
Users t1
And this look like better idea, since you don't want to have user names, so that's no need to involve Users table:
SELECT
User_ID,
GROUP_CONCAT(GroupName) AS GroupNames
FROM
(
SELECT
t2.User_ID AS User_ID,
t3.GroupName AS GroupName
FROM
User_Groups t2
LEFT JOIN
Groups t3 ON (t3.Group_ID = t2.Group_ID)
) tmp
GROUP BY
User_ID

Related

Select most "popular" follower for particular person. The more followers someone has, the more "popular" they are

Find most "popular" follower for a specific person. The more followers someone has, the more
"popular" they are.
I need SQL query to select most popular follower of particular people.
My Table - (followers)
id | person_id | follower_person_id
1 1 2
2 1 3
3 2 1
4 2 4
5 3 1
6 3 2
7 3 4
8 4 3
For example person_id 1 has total 2 follower, person_id 2 has total 2
followers, person_id 3 has total 3 followers and person_id 4 has total
2 followers.
Therefore, person_id 3 is most popular follower for person_id 1,
person_id 1 is most popular follower for person_id 2 and so on...
Here is my query but its not working...
SELECT follower_person_id FROM followers f where f.person_id = 1 group by f.follower_person_id having max(select count(*) from followers where person_id = f.follower_person_id)
You can use the following query to get the number of followers for each person:
SELECT person_id, COUNT(*) AS cnt
FROM followers
GROUP BY person_id
Output:
person_id cnt
-------------
1 2
2 2
3 3
4 1
Using the above query as a derived table you can get the number of followers for follower for each person (sounds a bit complicated!):
SELECT t1.person_id, t1.follower_person_id, t2.cnt
FROM followers AS t1
JOIN (
SELECT person_id, COUNT(*) AS cnt
FROM followers
GROUP BY person_id
) AS t2 ON t1.follower_person_id = t2.person_id
Output:
person_id, follower_person_id, cnt
------------------------------------
1, 2, 2
1, 3, 3
2, 1, 2
2, 4, 1
3, 1, 2
3, 2, 2
3, 4, 1
4, 3, 3
Since you are looking for just a specific person, you can use a WHERE clause in the above query:
SELECT t1.person_id, t1.follower_person_id, t2.cnt
FROM followers AS t1
JOIN (
SELECT person_id, COUNT(*) AS cnt
FROM followers
GROUP BY person_id
) AS t2 ON t1.follower_person_id = t2.person_id
WHERE t1.person_id = 1
ORDER BY t2.cnt DESC LIMIT 1
ORDER BY with LIMIT will give you the most popular person the specific person is following.
Output:
person_id, follower_person_id, cnt
-----------------------------------
1, 3, 3
Note: You can generalize the output of the second query using variables to get the most popular person each person follows (this is a greatest-per-group problem).
could you be looking for something like
SELECT person_id,COUNT(person_id) as followerCount FROM followers
GROUP BY person_id ORDER BY COUNT(person_id) DESC;
This will arbitrarily pick one of the most popular followers if there is a tie for a single person, but it does give the desired result.
SELECT
person_id,
(
SELECT
_f.follower_person_id
FROM
followers _f
WHERE
_f.person_id = f.person_id
GROUP BY
_f.follower_person_id
ORDER BY
COUNT( _f.follower_person_id ) DESC
LIMIT 1
)
FROM
followers f
GROUP BY
person_id
Working SQL Fiddle
You need to do group by person id not by follower id, should take follower_id count .
SELECT person_id ,count(follower_person_id) FROM followers f group by f.person_id
having count(follower_person_id)=(select max(f_cnt ) from
(select count(follower_person_id) f_cnt from followers group by person_id))
If there are 2 persons with same number of most popular then it will return those 2 person with same count
#Parth Can you try this smaller version, i think this is small and simple to understand
With temp as
(
select a.id, a.person_id, count(b.follower_person_id) as follower from
TableName a
inner join TableName b on a.person_id=b.follower_person_id
Group by a.person_id
)
select top 1 * from temp order by follower_person_id desc

sql select duplicates and singles

so i have a database table like:
NAME name_ID
---------------
Joao 1
Maria 3
Joao 1
carlos 2
carlos 2
i want to do a select query that displays all duplicates only like this :
NAME name_ID
---------------
Joao 1
Joao 1
carlos 2
carlos 2
and other select query that displays singles like so :
NAME name_ID
---------------
Maria 3
This would be simpler if you had a unique id column in each table. I encourage you to design tables with primary keys.
In any case, you can do this with a query of the form for duplicates:
select t.*
from databasetable t join
(select name, count(*) as cnt
from databasetable
group by name
) tt
on t.name = tt.name
where cnt > 1;
For singletons, the comparison would be cnt = 1.
EDIT:
With a unique id and an index on (name, id), the following is probably faster for duplicates:
select t.*
from databasetabe t
where exists (select 1
from databasetable t2
where t2.name = t.name and t2.id <> t.id
);
Singletons would use not exists instead.
select name from table group by name haveing count(*)=1 ###for Maria
select * from table where not in (previous select) order by name

Multiple Aggregate with different Group By

I have table User, Company, ParentCompany and table Goal.
Each Company have ParentCompany, and each User inside one Company. Goal have number of action, and type of Goal, user who execute the goal, and time executed.
I want to calculate the number of action in a date range for each type of Goal, for each user, company, and parent_company. Number of action for each company equal to sum of action for user that reside in that company.
More or less after some join query, I able to get this table below, where column id is id of company, parent_id is id of companyparent, and num is number of goal for all user inside of id company.
id parent_id num
----------- -------------------- -----------------------
1 3 1
2 1 2
3 1 1
4 2 4
Now I want to make it like below:
id parent_id sum_id sum_parent
----------- -------------------- -------------- -------------
1 3 1 1
2 1 2 3
3 1 1 3
4 2 4 4
How can I make it works? I can get one of the value (sum_id or sum_parent) with GROUP BY,
SELECT id,SUM(num) AS sum_id FROM tableA GROUP BY id
or
SELECT parent_id,SUM(num) AS sum_parent FROM tableA GROUP BY parent_id
but is there any way to make it only in one query? tableA results from query with 5 join inside.
Try this:
SELECT a.id, a.parent_id, a.sum_id, b.sum_parent
FROM (SELECT id, parent_id, SUM(num) sum_id FROM tableA a GROUP BY id) a
INNER JOIN (SELECT parent_id, SUM(num) sum_parent FROM tableA a GROUP BY parent_id) b ON a.parent_id = b.parent_id
Try this :
SELECT
t1.id, t1.parent_id, t1.sum_id, t2.sum_parent
FROM
(SELECT id, parent_id, SUM(num) AS sum_id FROM mytable GROUP BY id) t1
INNER JOIN
(SELECT parent_id, SUM(num) AS sum_parent FROM mytable GROUP BY parent_id) t2
ON t1.parent_id = t2.parent_id
Apparently what I want can be done with WITH ROLLUP statement. (http://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html)
With
SELECT id,sum(num) FROM tableA GROUP BY parent_id, id WITH ROLLUP;
will results in
parent_id id sum(num)
----------- -------------------- --------------
1 2 2
1 3 1
1 null 3
2 4 4
2 null 4
3 1 2
3 null 2

Counting unique numbers in a column MySQL

I have a query that returns data in the following format:
id | name | number
1 John 12545
1 John 50496
2 Mary 23443
3 Mark 54
3 Mark 5600
3 Mark 50206
I would like to find out the number of distinct ids that appear in the result set. For example, for the result above. I would like to obtain the value 3.
Is there any way to add a column so the result looks like this instead?
count | id | name | number
3 1 John 12545
3 1 John 50496
3 2 Mary 23443
3 3 Mark 54
3 3 Mark 5600
3 3 Mark 50206
My query is:
SELECT * FROM (
SELECT id FROM tableA
WHERE xyz
) as t1
JOIN tableB using (id)
SELECT (SELECT COUNT(DISTINCT id) FROM tableName) totalCount,
id,name,number
FROM tableName
or by using CROSS JOIN
SELECT x.totalCount,
a.id, a.name, a.number
FROM tableName a, (SELECT COUNT(DISTINCT id) totalCount
FROM tableName) x
You should try :
SELECT id,name,number, (SELECT COUNT(DISTINCT name) FROM YourTableName) FROM YourTableName
Good luck
SELECT COUNT(DISTINCT id) would be faster than using column name.
SELECT (SELECT COUNT(DISTINCT id) FROM tableName) as 'count',
id,name,number
FROM tableName
SELECT COUNT(id) AS count , id, name, number
FROM
(
SELECT id
FROM tableA
WHERE xyz
) as t1
JOIN tableB using (id)
GROUP BY id, name, number

MySQL statement: spliting rows values into new columns

Using MySQL I need to return new first/last name columns for each user in table1.
**Table1**
uid
1
2
**Table2**
id fid uid field_value
1 1 1 Joe
2 2 1 Blow
3 1 2 Joe
4 2 2 Blogs
**Result**
uid first_name last_name
1 Joe Blow
2 Joe Blogs
The solution is simple,
select t1.uid, t21.field_value first_name, t22.field_value last_name
from table1 t1, table2 t21, table2 t22
where t1.uid=t21.uid and t1.uid=t22.uid and t21.fid=1 and t22.fid=2
This should do it (not tested):
select a.uid, a.field_value first_name, b.field_value last_name
from table2 a inner join table2 b on a.uid = b.uid
where a.fid = 1 and b.fid = 2
assuming you have columns first_name, and last_name in table2:
select uid, first_name, last_name from table1 left join table2 on table1.uid=table2.uid