Reputation: 27174
I've got two tables: experiments and pairings.
experiments:
-experimentId
-user
pairings:
-experimentId
-tone
-color
Each experiment consists of seven pairings. A pairing consists of matching a color against a tone. And the experiment is repeated multiple times by a single user.
Now I'm trying to find out how to get the highest number of equal pairing per tone. Example:
user | tone | color | number of equal pairings
user1 | b4 | red | 5
user1 | c4 | blue | 4
user2 | b4 | green | 4
…
So far I can get all the equal pairings with the following query:
SELECT user, tone, color, COUNT(tone) as toneCounter
FROM experiments LEFT JOIN pairings ON experiments.experimentId = pairings.experimentId
GROUP BY user, tone, color
ORDER BY toneCounter DESC, user ASC
Which would look like this for example:
user | tone | color | number of equal pairings
user1 | b4 | red | 5
user1 | b4 | blue | 2
user1 | c4 | blue | 4
user1 | c4 | red | 1
user1 | c4 | green | 2
user2 | b4 | green | 4
…
Yet I'm not sure how to only get the top equal pairings only. So in the above example I would want to get rid of the other entries for b4 and c4 for user1, and only display b4 red and c4 blue.
I tried it with the following query, but apparently that is not valid SQL:
SELECT user, tone, color, COUNT(tone) as toneCounter
FROM experiments LEFT JOIN pairings ON experiments.experimentId = pairings.experimentId
GROUP BY user, tone, color
HAVING toneCounter = (select max(COUNT(tone)) as tc from pairings as p where p.tone = pairings.tone)
ORDER BY toneCounter DESC, user ASC
How can I do this?
Upvotes: 1
Views: 165
Reputation: 401
2 SQL-Statments, the 2nd should do it...
SELECT
AA.user, AA.tone, AA.color, MAX(AA.toneCounter) as toneCounter
FROM (
SELECT
user, tone, color, COUNT(tone) as toneCounter
FROM
experiments
LEFT JOIN
pairings
ON
experiments.experimentId = pairings.experimentId
GROUP BY
user, tone, color
) AA
Group by
AA.user, AA.tone
... my answer did not satisfy myself and I doublechecked it. And I think the next answer is more adequate (and even runs on no-mysql)
SELECT
AAA.user, AAA.tone, BBB.color, AAA.toneCounter
FROM (
SELECT
AA.user, AA.tone, MAX(AA.toneCounter) as toneCounter
FROM (
SELECT
user, tone, color, COUNT(tone) as toneCounter
FROM
experiments
LEFT JOIN
pairings
ON
experiments.experimentId = pairings.experimentId
GROUP BY
user, tone, color
) AA
Group by
AA.user, AA.tone
) AAA
join (
SELECT
BB.user, BB.tone, BB.color, MAX(BB.toneCounter) as toneCounter
FROM (
SELECT
user, tone, color, COUNT(tone) as toneCounter
FROM
experiments
LEFT JOIN
pairings
ON
experiments.experimentId = pairings.experimentId
GROUP BY
user, tone, color
) BB
Group by
BB.user, BB.tone, BB.color
) BBB
ON
BBB.user = AAA.user
AND BBB.tone = AAA.tone
AND BBB.toneCounter = AAA.toneCounter
Upvotes: 2
Reputation: 580
create table experiments(
experimentId int identity(1,1),
[user] nvarchar(256));
create table pairings(
experimentId int,
tone nvarchar(256),
color nvarchar(256));
insert into experiments([user]) values ('user1');
insert into experiments([user]) values ('user1');
insert into experiments([user]) values ('user1');
insert into experiments([user]) values ('user2');
insert into experiments([user]) values ('user1');
insert into experiments([user]) values ('user1');
insert into experiments([user]) values ('user1');
insert into pairings(experimentId, tone,color) values (1,'b4','red');
insert into pairings(experimentId, tone,color) values (2,'b4','red');
insert into pairings(experimentId, tone,color) values (3,'c4','green');
insert into pairings(experimentId, tone,color) values (4,'c4','blue');
insert into pairings(experimentId, tone,color) values (5,'b4','red');
insert into pairings(experimentId, tone,color) values (6,'b4','green');
insert into pairings(experimentId, tone,color) values (7,'b4','green');
IF OBJECT_ID('tempdb..#tempData') IS NOT NULL DROP TABLE #tempData;
IF OBJECT_ID('tempdb..#tempTones') IS NOT NULL DROP TABLE #tempTones;
select a.[user],b.tone,b.color,count(b.tone) as toneCounter into #tempData
from experiments a inner join pairings b on a.experimentId=b.experimentId
group by a.[user],b.tone,b.color
order by toneCounter desc,a.[user] asc;
select distinct [user],tone into #tempTones from #tempData;
with cte as(
select a.[user],a.[tone],max(a.toneCounter) as toneCounter from #tempData a inner join
#tempTones b on (b.[user]=a.[user] and b.tone=a.tone) group by a.tone,a.[user]
)
select a.* from #tempData a inner join cte b on
(b.[user]=a.[user] and a.toneCounter=b.toneCounter and a.tone=b.tone)
Upvotes: 1
Reputation: 544
If I understand your question correctly, what I will do is, firstly, retrieving the maximum tone counter of each tone for each user from the result table you got. Secondly, I will use that info to left join with the same result table you got to get the final result.
SELECT OriRef.*
FROM
(
SELECT user, tone, MAX(toneCounter) AS maxToneCounter
FROM
(
SELECT user, tone, color, COUNT(tone) as toneCounter
FROM experiments LEFT JOIN pairings ON experiments.experimentId = pairings.experimentId
GROUP BY user, tone, color
) AS Ref
) AS MaxRef
LEFT JOIN
(
SELECT user, tone, color, COUNT(tone) as toneCounter
FROM experiments LEFT JOIN pairings ON experiments.experimentId = pairings.experimentId
GROUP BY user, tone, color
) AS OriRef ON MaxRef.user = OriRef.user AND MaxRef.tone = OriRef.tone AND MaxRef.maxToneCounter = OriRef.toneCounter
Please correct me if I'm wrong.
Upvotes: 1