Count duplicate records - php

Suppose I have a table named studens.
I want to count how many students who received duplicated scores at least 2 times.
Please help me, thanks.
The result that I expect is: Jonh have 100 score 2 times, James have 80 scores 2 times, Julia has 50 scores 2 times. So the amount of students who receive duplicated score at least 2 times is 3 (Jonh, Jam, and Julia).

select count(*) from
(
select name
from your_table
group by name, score
having count(*) > 1
) x

Based on the edit, your query would be:
select distinct name
from students
group by name, score
having count(*) > 1;
You could see the scores and counts by doing:
select name, score, count(*)
from students
group by name, score
having count(*) > 1;
By the way, the first query is one of the very, very few times where select distinct is appropriate with a group by. I think the second query provides more information, though.

Assuming a student has only one score per subject (that is, name, subject is unique):
SELECT COUNT(DISTINCT t1.name)
FROM scores t1
INNER JOIN scores t2
ON t1.name = t2.name
AND t1.subject <> t2.subject
AND t1.score = t2.score
SQLFiddle

Related

Getting team rank with SQL query

I have this SQL query for getting the rank number of a team in my database based on their 'point'.
SELECT id, points, team_name, FIND_IN_SET( points, (
SELECT GROUP_CONCAT( points
ORDER BY points DESC )
FROM teams )
) AS rank
FROM teams
WHERE id = ?
LIMIT 1
The problem I'm having is that given the scenario that two teams have the same points e.g. say there is 2 teams and each team has '0' points. The query returns rank '1' for both of the teams.
I want the team with the lower 'id' to have the higher rank between the teams with the same points.
For example say team1 and team2 both have '5' points. I want the team with the lower id to have rank 1.
How can I alter my query to do that?
Thanks
The method you are using has limited applicability in MySQL, because it depends on the length of the intermediate substring in the group_concat(). However, you can modify it for this purpose:
SELECT id, points, team_name,
FIND_IN_SET(CONCAT(points, ':', id),
(SELECT GROUP_CONCAT(points, ':', id ORDER BY points DESC, id )
FROM teams
)
) AS rank
FROM teams
WHERE id = ?
LIMIT 1;
A better method is:
select id, points, team_name,
(select count(*)
from teams t2
where t2.points > t.points or
(t2.points = t.points and t2.id <= t.id)
) as rank
from teams t
where id = ?;

Need the highest ID using left join

I have two tables,
TABLE 1 has many of each client and campaign and is very large
TABLE 2 has only one of each client and campaign and is small.
So I want to get the lastest(highest ID) from TABLE 1 where it matches the client and campaign in TABLE 2 and only one of each.
I have tried MAX, and playing with the order by etc, but cant get it working....
The results I get are choosing the lowest ID from TABLE 1 (I want highest)
$result2 = mysql_query("SELECT table1.client,table1.campaign,table1.id
FROM table1
LEFT OUTER JOIN
table2
ON (table2.client = table1.client)
AND (table2.campaign = table1.campaign )
WHERE (table2.enabled != 'disabled')
group by campaign asc
order by client,campaign,id asc
");
Help needed....
SELECT * FROM table1
INNER JOIN
(
SELECT MAX(table1.id) AS id FROM table1
INNER JOIN table2 ON table2.client = table1.client AND table2.campaign=table1.campaign and table2.enabled != 'disabled'
GROUP BY table1.client, table1.campaign
) AS m ON m.id = table1.id
I think that's what you're asking for. For each combination of client and campaign that exists in each table, it will give you the highest ID in table 1.

PHP / MYSQL Statement so select Max Sum of Join

I have Problems with a select statement, as a little help here are the important columns:
Table1
ID NAME
TABLE 2
ID U_ID COUNTER
The ID of Table 1 Matches the U_ID of Table 2. Table 2 contains many entries for the same u_id.
What I want to do is to get the Name of the "user" (table 1) who has in sum the max. counter.
What I got since now is the join of the tables (Where clause depends on other rows which are not important for the problem).
Can anyone help me on this issue?
So what you need is an aggregate of an aggregate (max of sum of column). The easiest will be to create a view providing the sum and u_id end then select the max of it:
create view table2sums
as
select u_id, sum(counter) as total
from table2
group by u_id;
and then
select t1.name
from table1 t1, table2sums t2
where t1.id = t2.u_id
and t2.total >= all (
select total
from table2sums
)
In this special case you can also do it directly:
select t1.name
from table1 t1, table2 t2
where t1.id = t2.u_id
group by t1.name
having sum(t2.counter) >= all (
select sum(counter)
from table2
group by t2.u_id
)
NOTE: The other proposed solutions will show a better performance. My solution only selects the name (which is what you said you wanted) and works in any RDBMS.
There exist RDBMS without the LIMIT possibility.
In the end, I'd say: regard my solution as educational, the others as practical
SELECT name,
SUM(counter) as counter
FROM table1
JOIN table2
ON table1.id = table2.u_id
GROUP BY u_id
ORDER BY counter DESC
LIMIT 1
You can try this:
SELECT name, SUM(counter) as total_counter
FROM table1
JOIN table2
ON table1.id = table2.u_id
GROUP BY u_id
ORDER BY total_counter DESC
LIMIT 1
Working Demo: http://sqlfiddle.com/#!2/45419/4

query with if and count

trying to add if condition to do the following
1- selecting data depending on if that data selected before by the user
2- selecting data depending on how many time that data was selected by all users
3- setting maximum number of how many times the data could be selected by all user
here is my current code as you can see all that i made the first condition and it work fine
$sql=mysql_query(
"SELECT courseid,coursename
FROM newcourses
where (courseid not in (select courseid from applicants)
)"
);
for example :
if i have table newcourses that have these rows
courseid coursename max applicant
1 English standard 3
2 English advance 2
3 Spanish 4
and table applicants have these rows
id name courseid
1 me 1
2 jon 1
3 jake 2
4 sara 2
5 joe 3
so how to do so
Try something like this:
SELECT n.courseid, n.coursename
FROM newcourses n
LEFT JOIN applicants a ON n.courseid = a.courseid
GROUP BY n.courseid, n.coursename
HAVING count(a.id) <=1;
This will get all the courses that don't have any applicants and the ones that have one applicant.
And it doesn't use a subquery that has to run once for every record selected, so you gain on performance also.
This uses a LEFT JOIN between newcourses and applicants tables. This shows any element of newcourses that have records in applicants table but shows also the ones that aren't in the applicants table (that's the reason to use LEFT JOIN).
sqlfiddle demo
If you want to check them separately you can do:
To get the courses with no applicants:
SELECT n.courseid, n.coursename
FROM newcourses n
LEFT JOIN applicants a ON n.courseid = a.courseid
GROUP BY n.courseid, n.coursename
HAVING count(a.id) = 0;
To exclude courses with two applicants:
SELECT n.courseid, n.coursename
FROM newcourses n
LEFT JOIN applicants a ON n.courseid = a.courseid
GROUP BY n.courseid, n.coursename
HAVING count(a.id) != 2;
If you can't have more than two, you can change the != to <
If you end up adding a new column to newcourses with the max number of applicants, you can't put that in an external HAVING COUNT, so you would have to do a subquery:
SELECT n.courseid, n.coursename
FROM newcourses n
LEFT JOIN applicants a ON n.courseid = a.courseid
WHERE n.maxApplicants >= (SELECT count(*)
FROM applicants ap WHERE ap.courseid = n.courseid)
GROUP BY n.courseid, n.coursename
Is this what you want to do ?
$sql = mysql_query(
"SELECT courseid,coursename
FROM newcourses
WHERE (courseid NOT IN (SELECT courseid FROM applicants GROUP BY courseid HAVING( COUNT( courseid ) > 1)))
"
);
"HAVING (COUNT (courseid) > 1))" will return multiples ocurences values of the table "applicants".
You must include all negative rows on subquery by using filter like GROUP BY - HAVING.
SELECT courseid, coursename
FROM newcourses
WHERE courseid NOT IN (SELECT courseid FROM applicants GROUP BY courseid HAVING COUNT(courseid) > 1)
Easier to read:
SELECT courseid, coursename
FROM newcourses
WHERE courseid IN (SELECT courseid FROM applicants GROUP BY courseid HAVING COUNT(courseid) = 1)
SELECT courseid,coursename
FROM newcourses
where courseid not in (select courseid from applicants GROUP BY courseid HAVING COUNT(courseid)=2)
If you want to ignore courseids which are triplets or more use HAVING COUNT(courseid)>1

Count average age from database, merge 2 queries

Ok so I don't think the question is as simple as the title suggests but here goes ...
I have this query:
SELECT age.*, job.id FROM age, job WHERE ((age.aid = job.id) AND (age.aid='$id'))
this basically joins the two tables age and job and gets matching rows
but now I need to find the most common age stored in row guess under the table age
DB layout
Table: age
rows: aid - guess
Table: job
Rows: id
From what I have found searching I need to use count()
eg:
SELECT guess, COUNT(guess) AS countguess FROM age GROUP BY guess ORDER BY countguess DESC LIMIT 1
but how can I merge the 2 queries together?
You could do something like this
SELECT age.aid, job.id, age.guess, COUNT(age.guess) AS countguess
FROM age, job
WHERE ((age.aid = job.id) AND (age.aid='$id'))
GROUP BY guess
ORDER BY countguess DESC
When you say merge, i think you mean joining them. You can join when there is a relationship between the 2 tables.
You can use UNION ALL to accomplish this
SELECT aid, id, guess, SUM(countguess ) AS countguess
FROM
(
SELECT age.aid, job.id, guess, 0 AS countguess
FROM age
INNER JOIN job
ON age.aid = job.id AND
age.aid='$id'
UNION ALL
SELECT age.aid, 0 AS job.id, guess, COUNT(guess) AS countguess
FROM age
GROUP BY guess
ORDER BY countguess DESC
LIMIT 1
) a
GROUP BY aid
*Note: UNION ALL requires same number of columns in both queries
SELECT age.*, job.id FROM age, job,
(SELECT AVG(guess) AS countguess FROM age GROUP BY guess ORDER BY countguess DESC LIMIT 1) AS countguess
FROM job AS j
INNER JOIN age AS a
ON j.id = a.aid
WHERE a.aid = '{$id}'
I'm not sure if this is what you want? Maybe
SELECT age.*, job.id FROM age, job,
(SELECT AVG(guess) AS countguess FROM age WHERE guess = a.guess GROUP BY '1') AS countguess
FROM job AS j
INNER JOIN age AS a
ON j.id = a.aid
WHERE a.aid = '{$id}'

Categories