I have a table users like this:
id user refid
1 a null
2 b 1
3 c 1
4 d 2
5 f 3
I need to select the users, grouping by refid and the count of each refid for each user. For example,
id user count
1 a 2
2 b 1
3 c 1
This is what I have tried:
SELECT user, refid, count(*) cnt FROM `users` group by refid
However, this gives me the wrong user for each value. How can I get the correct user for each value?
I guess this is what you're looking for. Basically, you're missing a join there.
select u1.id, u1.user, count(u1.id) cnt from mlm_users u1
join mlm_users u2 on u1.id = u2.refid
group by u1.id, u1.user
This will return the id, user and the amount of referrals each of them have (only for the ones that have at least one referral).
You need to group by the user and refid
SELECT user, refid, count(*) cnt FROM `mlm_users` group by user,redid
Related
I have two tables named table1 and table2:
Table1
id date email cId
1 2013-08-28 12:21:39 t#gmail.com 12345
2 2013-07-27 10:15:18 k#gmail.com 12345
3 2018-02-13 09:41:43 a#gmail.com 12345
4 2018-02-02 10:14:42 n#gmail.com 45678
5 2017-11-16 10:16:51 l#gmail.com 45678
Table2
id status
12345 1
45678 1
56789 0
When I execute a query I am expecting to get row from table1 which has max date.
select c.id 'table 2 Id'
, DATE_FORMAT(Max(u.date),'%Y-%m-%dT%TZ') 'Date'
, u.email 'User'
from table2 c
LEFT
JOIN table1 u
ON u.cId = c.id
where c.status = 1
group
by c.id
order
by c.id;
How ever what I see is kind of confusing.
table 2 Id Date USER
12345 2018-02-13 09:41:43 t#gmail.com
I am expecting the output to be
table 2 Id Date USER
12345 2018-02-13 09:41:43 a#gmail.com
Because the max date that is selected is not same of the user t#gmail.com but of a#gmail.com
Any suggestions on where has it gone wrong and how can I tweak it to get correct result?
The moment you use a grouping function (i.e. max, sum, count, etc.) you must specify only segregating columns in the SELECT clause.
In your case, there are several emails for one given id, much like the date field.
You can't just specify
SELECT id, max(date), email ...
it wouldn't make sense, because you need to specify a grouping function for the mail.
What you're really interested in, is "the email that corresponds to the row whose date is max(date) for a given id".
This must be done using a subquery. Something like this:
SELECT
tmax.cid,
tmax.maxdate,
table1.email,
table2.status
FROM
table2
INNER JOIN table1
ON table1.cid = table2.id
INNER JOIN (
SELECT
cid,
max(date) AS maxdate
FROM
table1
GROUP BY
cid
) AS tmax
ON tmax.cid = table1.cid AND tmax.maxdate = table1.date;
The above query executed on your data set, will give this exact output (2 rows):
cid maxdate email status
12345 2018-02-13 09:41:43 a#gmail.com 1
45678 2018-02-02 10:14:42 n#gmail.com 1
which means, in English: "For each id in table2, bring its status, and bring the line in table1 for the corresponding cid, and whose date is the max date for same cid within table1."
Because I used INNER JOINs, the records in table1 that mention a cid that does not exist in table2, are discarded.
You could write the query like this (add an order desc on u.date):
SELECT c.id 'table 2 Id', DATE_FORMAT(MAX(u.date),'%Y-%m-%dT%TZ') 'Date', u.email 'User'
FROM table2 c
LEFT JOIN table1 u ON u.cId = c.id
WHERE c.status = 1
GROUP BY c.id
ORDER BY c.id, u.date DESC;
I'm trying to get count of duplicate data, but my query doesn't work correctly.
Every user should have one dev_id but when other user will have this same dev_id I want to know this
Table for example:
dev_id user_id
------------------
111 1
111 1
222 2
111 2
333 3
Should result:
user_id qu
------------------
1 1
2 1
3 0
This is my query
SELECT t1.user_id,
(SELECT Count(DISTINCT t2.dev_id)
FROM reports t2
WHERE t2.user_id != t1.user_id
AND t2.dev_id = t1.dev_id
) AS qu
FROM reports t1
GROUP BY t1.user_id
You can get results by doing:
select r.user_id, count(*) - 1
from reports r
group by r.user_id;
Is this the calculation that you want?
Okay. Let start from simple.
First you need get unique user_id/dev id combinations
select distinct dev_id,user_id from reports
Result will be
dev_id user_id
------------------
111 1
222 2
111 2
333 3
After that you should get number of different user_id per dev_id
select dev_id,c from (
SELECT
dev_id,
count(*)-1 AS c
FROM
(select distinct user_id,dev_id from reports) as fixed_reports
GROUP BY dev_id
) as counts
Result of such query will be
dev_id c
-----------------
111 1
222 0
333 0
Now you should show users which have such dev_id. For that you should join such dev_id list with table from step1(which show which one user_id,dev_id pairs exist)
select distinct fixed_reports2.user_id,counts.c from (
SELECT
dev_id,
count(*)-1 AS c
FROM
(select distinct user_id,dev_id from reports) as fixed_reports
GROUP BY dev_id
) as counts
join
(select distinct user_id,dev_id from reports) as fixed_reports2
on fixed_reports2.dev_id=counts.dev_id
where counts.c>0 and counts.c is not null
"Distinct" here need to skip same rows.
Result should be for internal query
dev_id c
-----------------
111 1
For all query
user_id c
------------------
1 1
2 1
If you sure you need also rows with c=0, then you need do "left join" of fixed_reports2 and large query,that way you will get all rows and rows with c=null will be rows with 0(can be changed by case/when statement)
I think following sql query should solve you problem:
SELECT t1.user_id, t1.dev_id, count(t2.user_id) as qu
FROM (Select Distinct * from reports) t1
Left Join (Select Distinct * from reports) t2
on t1.user_id != t2.user_id and t2.dev_id = t1.dev_id
group by t1.user_Id, t1.dev_id
SQL Fiddle Link
SELECT user_id, (COUNT(user_id) -1) as qu
FROM reports
GROUP BY user_id
This would give desired result in your case, however you can improve it a lot more.
Cheers,,
Your query is broken and would not run on many systems. The problem is that the group with user_id of 2 has two different dev_ids. If you run the "broken query" below you can see that the min() and max() are distinct but the subquery only sees one of those values which is randomly chosen. The last query is corrected by adding dev_id to the groupings which shows you where the "missing" row went in the counts.
SELECT -- broken query
t1.user_id, min(t1.dev_id), max(t1.dev_id),
(select distinct t1.dev_id from reports) as should_have_errored,
(SELECT Count(DISTINCT t2.dev_id)
FROM reports t2
WHERE t2.user_id != t1.user_id
AND t2.dev_id = t1.dev_id
) AS qu
FROM reports t1
GROUP BY t1.user_id;
-- On SQL Server that query returns an error
-- Msg 8120, Level 16, State 1, Line 7
-- Column 'reports.dev_id' is invalid in the select list because it is
-- not contained in either an aggregate function or the GROUP BY clause.
SELECT -- query that duplicates your original query
t1.user_id,
(SELECT Count(DISTINCT t2.dev_id)
FROM reports t2
WHERE t2.user_id != t1.user_id
AND t2.dev_id = max(t1.dev_id) /* <-- see here */
) AS qu
FROM reports t1
GROUP BY t1.user_id;
SELECT t1.user_id, t1.dev_id, -- fixed query
(SELECT Count(DISTINCT t2.dev_id)
FROM reports t2
WHERE t2.user_id != t1.user_id
AND t2.dev_id = t1.dev_id
) AS qu
FROM reports t1
GROUP BY t1.user_id, t1.dev_id
http://sqlfiddle.com/#!9/6576e3/20
Here are some queries that might be useful:
Which dev_ids have multiple user_ids associated with them?
select dev_id
from reports
group by dev_id
having count(distinct user_id) > 1
Which other user_ids share a dev_id with this user_id?
select user_id
from reports r1
where exists (
select 1
from reports r2
where r2.dev_id = r1.dev_id and r2.user_id <> ?
)
Or really that's just equivalent to an inner join which also makes it easy to list everybody at once. Note that each pair will be listed twice:
select r1.user_id, r1.dev_id, r2.user_id as common_user_id
from
reports r1 inner join reports r2
on r2.dev_id = r1.dev_id
where
r1.user_id <> r2.user_id
order by
r1.user_id, r1.dev_id, r2.user_id
And since you've got duplicate rows in your table you'd need to make it select distinct to get unique rows.
Try
SELECT
user_id,
SUM(qu) AS qu
FROM (
SELECT
user_id,
count(*)-1 AS qu
FROM
reports
GROUP BY user_id, dev_id
) AS r
GROUP BY user_id
No need to do a join if all the data you need is in one table.
Edit: changed the group by to dev_id instead of user_id
Edit2: I think you need both dev_id and user_id in the group by clause.
Edit3: Added a subquery to get the desired result. This might be a little cumbersome, perhaps someone has a way to improve this?
Let's assume that I have the following table:
id player_name team
1 Gladiator A
2 DarkLord B
3 Alligator A
4 MonaLisa C
5 SpongBob C
6 Mikasa B
I want to select one player from each team, which means that all the selected rows must have a unique value in the 'team' column. How can I accomplish this in MySQL?
In my example the selected rows should be:
id player_name team
1 Gladiator A
2 DarkLord B
4 MonaLisa C
This is one way to do it using a derived table so you select one id per team and join it to the original table.
select t.id, t.player_name, t.team
from tablename t
join (select team, min(id) as minid from tablename group by team) x
on x.team = t.team and x.minid = t.id
One simple way would be to fetch using a group by criteria. (Assuming your table name is TEAM_TABLE)
SELECT * FROM TEAM_TABLE GROUP BY TEAM;
This would return the first record occurring for each value of the team column.
My query is so close, i've gone through almost all the other times this has been posted, but I'm not quite there.
SELECT a.name, IFNULL(b.student_id, 0) AS count
FROM student AS a
LEFT JOIN (SELECT student_id, COUNT(*) as count FROM quizactivity GROUP BY student_id)
AS b
ON a.id = b.student_id;
This returns a table with the names of the four entries, and then their actual id on their own table, a.id.
Name | Count
Will 1
Jane 2
Sally 0
Dave 4
Sally returns 0 because she has no results.
I am cleary returning the id of the table instead of the counts - where am I wrong?
Don't you want the count?
SELECT a.name, COALESCE(b.count, 0) AS count
FROM student a LEFT JOIN
(SELECT student_id, COUNT(*) as count
FROM quizactivity
GROUP BY student_id
) b
ON a.id = b.student_id;
I am trying to write a query that returns a users profile information, along with a count of occurrences of the user's ID in 2 columns from another table. An example below:
TableA
userID userName
1 UserA
2 UserB
TableB
LinkID leadID followID
1 1 2
2 1 3
3 2 1
Querying against UserID 1 I would expect to retrieve UserA, 2 (occurences of 1 in leadID), and 1 (occurences of 1 in followID). Any help with this is much appreciated, and thanks in advance.
You don't actually need to join for this - you can instead make three separate selects.
SELECT
(
SELECT userName
FROM TableA
WHERE userID = 1
) AS userName,
(
SELECT COUNT(*)
FROM TableB
WHERE leadID = 1
) AS count_leadID,
(
SELECT COUNT(*)
FROM TableB
WHERE followID = 1
) AS count_followID
Result:
userName count_leadID count_followID
UserA 2 1
SELECT a.userName,
SUM(IF(b.leadId = a.userId, 1, 0) as Leads,
SUM(IF(b.followId = a.userId, 1, 0) as Follows
FROM TableA a
TableB b
GROUP BY a.userName
SELECT a.userName,
b1.count(*) as leads,
b2.count(*) as follows
FROM TableA a
INNER JOIN TableB b1 on a.userID = b1.leadID
INNER JOIN TableB b2 on a.userID = b2.followID
GROUP BY a.userName
Depending on how mySQL optimizes and if you have an index on leadID and followID then this could speed up the query, especially if you're going to query just a few users rather than them all at the same time.