join user id from tblB to user from tblA and get username - mysql

how to join userid to user and get the username ?
I really appreciate any help.Thanks in Advance.
http://sqlfiddle.com/#!2/ac600/1
CREATE TABLE if not exists tblA
(
id int(11) NOT NULL auto_increment ,
user varchar(255),
category int(255),
PRIMARY KEY (id)
);
CREATE TABLE if not exists tblB
(
id int(11) NOT NULL auto_increment ,
username varchar(255),
userid int(255),
PRIMARY KEY (id)
);
INSERT INTO tblA (user, category ) VALUES
('1', '1'),
('1', '2'),
('1', '3'),
('1', '1'),
('2', '1'),
('2', '1'),
('2', '1'),
('2', '1'),
('3', '1'),
('2', '1'),
('4', '1'),
('4', '1'),
('2', '1');
INSERT INTO tblB (userid, username ) VALUES
('1', 'A'),
('2', 'B'),
('3', 'C'),
('4', 'D'),
('5', 'E');
query:
SELECT
groups.*,
#rank:=#rank+1 AS rank
FROM
(select
user,
category,
count(*) as num
from
tblA
where
category=1
group by
user,
category
order by
num desc,
user) AS groups
CROSS JOIN (SELECT #rank:=0) AS init
the table looks like :
username category num Ascending rank
B 1 6 2
A 1 2 1
D 1 2 4
C 1 1 3

Use JOIN, for example:
SELECT
tblB.username,
groups.*,
#rank:=#rank+1 AS rank
FROM
(select
user,
category,
count(*) as num
from
tblA
where
category=1
group by
user,
category
order by
num desc,
user) AS groups
-- left join: in case if data integrity fails:
left join
tblB ON groups.user=tblB.userid
CROSS JOIN (SELECT #rank:=0) AS init
-check your modified demo.

You just need to do left join
SELECT
groups.*,
#rank:=#rank+1 AS rank
FROM
(select
user,
category,
count(*) as num,
tblB.username
from
tblA
left join tblB on tblA.id = tblB.userid
where
category=1
group by
user,
category
order by
num desc,
user) AS groups
CROSS JOIN (SELECT #rank:=0) AS init
See Demo

You don't need a subquery to do what you want. You can simply join in the name:
select username, category,
count(*) as num,
#rank:=#rank+1 AS rank
from tblA join
tblB
on tblA.user = tblB.userId CROSS JOIN
(SELECT #rank:=0) AS cont
where category = 1
group by username, category
order by num desc, username;
TblB has an odd format. Normally, the auto-incrementing id would be the "userid" for the table.
Also, because you are selecting only one category, strictly speaking it is unnecessary to put category in the group by statement.
EDIT:
You cannot create a view with this method of doing the rank because it uses variables. It isn't easy to generate a rank on aggregated data in a view-compatible way in MySQL.

Related

Group and subquery issue

This is my sample data
CREATE TABLE customer1
(
rating int(9),
genre varchar(100),
title varchar(100)
);
INSERT INTO customer1 (rating, genre, title)
VALUES
(2, 'A', 'abc'),
(4, 'A', 'abc1'),
(2, 'B', 'abc2'),
(3, 'B', 'abc3'),
(2, 'C', 'abc4'),
(5, 'C', 'abc5');
I need to find the title with max rating in each genre.
Thanks for the help.
One option uses a subquery for filtering:
select c.*
from customer1
where c.rating = (select max(c1.rating) from customer1 c1 where c1.genre = c.genre)
This would take advantage of an index on (genre, rating).
In MySQL 8.0, you can also use window functions:
select *
from (
select c.*,
rank() over(partition by genre order by rating desc) rn
from customer1 c
) c
where rn = 1

SQL: Find top n in groupby data

I have a table like this:
id | name | surname | city|
-------------------------------
'1', 'mohit', 'garg', 'delhi'
'2', 'mohit', 'gupta', 'delhi'
'3', 'ankita', 'gupta', 'jaipur'
'4', 'ankita', 'garg', 'jaipur'
'5', 'vivek', 'garg', 'delhi'
I am looking for a query that returns (id,city) grouped by city, with at most two (id) per city, but without using nested queries.
Expected output:
'1', 'delhi'
'2', 'delhi'
'3', 'jaipur'
'4', 'jaipur'
Perhaps the only way without subqueries is to use a trick with substring_index() and group_concat():
select city, substring_index(group_concat(id), ',', 2)
from t
group by city;
This puts the ids in a comma-delimited list, rather than in separate rows. Also, you have to be careful about the size of the intermediate results.
Of course, the accepted practice would use either a subquery in the where clause or a subquery using variables.
EDIT:
Here is a method for getting two ids per city without listing the cities:
select city, min(id) as id
from t
group by city
union
select city, max(id)
from t
group by city;
You can do this with a LEFT OUTER JOIN, although using a subquery will probably be clearer and might be faster. Here's a method using the JOIN:
SELECT
T1.id,
T1.city
FROM
My_Table T1
LEFT OUTER JOIN My_Table T2 ON T2.city = T1.city AND T2.id <= T1.id
GROUP BY
T1.id,
T1.city
HAVING
COUNT(*) <= 2
You're effectively finding all rows in T1 where the number of rows with the same name and a lower id is <= 2, which means that it must be one of the top two rows by id.
Try like below
create table
#test (id int, name varchar(10), name2 varchar(10),place varchar(10))
insert into #test
select
'1', 'mohit', 'garg', 'delhi'
union
select
'2', 'mohit', 'gupta', 'delhi'
union
select
'3', 'ankita', 'gupta', 'jaipur'
union
select
'4', 'ankita', 'garg', 'jaipur'
union
select
'5', 'vivek', 'garg', 'delhi'
with data
as
(
select ROW_NUMBER() OVER(PARTITION BY place ORDER BY id) RN,id,name,name2,place
from #test
),
data1
as(
select id, place
from data
where rn <=2
)
select *from data1

unable to group by category and unixtime desc

I have created: http://sqlfiddle.com/#!2/7bb44/1
CREATE TABLE if not exists tblA
(
id int(11) NOT NULL auto_increment ,
userid int(255),
category int(255),
unixtime int(255),
PRIMARY KEY (id)
);
INSERT INTO tblA (userid,category,unixtime) VALUES
('1', '1','1438689946'),
('1', '2','1438690005'),
('1', '3','1438690007'),
('5', '1','1438690009'),
('2', '1','1438690005'),
('2', '1','1438690398'),
('1', '2','1438691020'),
('1', '3','1438691028'),
('4', '2','1438690005'),
('2', '3','1438691025'),
('2', '2','1438691020'),
('3', '3','1438691022');
and
Select * from tblA group by category order by unixtime desc;
But I am getting wrong values.The values do not contain right unixtime desc.How can I make it work ? I really appreciate any help.
Try this query . If 2 unixtime are same this should display only 1
Select a.*
from tblA a join
(select category, max(unixtime) as maxut
from tblA
group by category
) c
on a.category = c.category and a.unixtime = c.maxut
group by unixtime order by a.unixtime desc;
You cannot express what you want in the way you have done it. The order by is processed after the group by. Presumably you want:
Select a.*
from tblA a join
(select category, max(unixtime) as maxut
from tblA
group by category
) c
on a.category = c.category and a.unixtime = c.maxut
order by a.unixtime desc;

get count of all users for particular category and rank them

how do I get count of each user contribution/appearing for that particular category.The table below has user,category .I am looking for count of hoe many times all users have contributed/appeared in the table below and rank them.
http://sqlfiddle.com/#!2/d4458/2
CREATE TABLE if not exists tblA
(
id int(11) NOT NULL auto_increment ,
user varchar(255),
category int(255),
PRIMARY KEY (id)
);
INSERT INTO tblA (user, category ) VALUES
('1', '1'),
('1', '2'),
('1', '3'),
('1', '1'),
('2', '1'),
('2', '1');
Response like: Search for category where its '1'
user category count rank
1 1 2 1
2 1 2 2
SELECT USER,
category,
count(*) AS num
FROM tblA
WHERE category=1
GROUP BY USER,
category
ORDER BY num DESC;
demo: http://sqlfiddle.com/#!2/d4458/10/0
SET #prev_value = NULL;
SET #rank_count = 0;
SELECT
i.*,
CASE
WHEN #prev_value = i.num THEN #rank_count
ELSE #rank_count := #rank_count + 1
END AS rank
FROM (
SELECT
user,category,COUNT(*) AS num
FROM tblA
WHERE category=1
GROUP BY user,category
ORDER BY num DESC
) i;

rank users based on count num

how to rank users based on column num which is count of number of times user exists in table.Also if 2 users have same count it should give the user on top rank lesser than below eg: user 1 and 2 has count 3 then user 1 is rank 1 and user 2 is rank 3 and if there is new user 3 with count 1 then user 3 is rank 3 .
How do I do that? I really appreciate any help.Thank in Advance.
http://sqlfiddle.com/#!2/a9188/2
CREATE TABLE if not exists tblA
(
id int(11) NOT NULL auto_increment ,
user varchar(255),
category int(255),
PRIMARY KEY (id)
);
INSERT INTO tblA (user, category ) VALUES
('1', '1'),
('1', '2'),
('1', '3'),
('1', '1'),
('2', '1'),
('2', '1'),
('2', '1'),
('2', '1'),
('3', '1'),
('2', '1');
Response like: Search for category where its '1'
user category count rank
1 1 2 1
2 1 2 2
query used:
SELECT USER,
category,
count(*) AS num
FROM tblA
WHERE category=1
GROUP BY USER,
category
ORDER BY num DESC;
For example, using subquery:
SELECT
groups.*,
#rank:=#rank+1 AS rank
FROM
(select
user,
category,
count(*) as num
from
tblA
where
category=1
group by
user,
category
order by
num desc,
user) AS groups
CROSS JOIN (SELECT #rank:=0) AS init
-check your modified demo.