Filter duplicates from mysql result depending on column value - mysql

I'm having some problems working out how to return the desired rows from the following mysql table:
first_name last_name collection
==========================================
Bob Jones 1
Ted Jones 1
Bob Jones 1
Bob Jones 2
Ted Baker 2
I want to return the count of names based on columns 'first_name' and 'last_name'. Ordinarily it would just be a simple case of using 'group by first_name, last_name', so we would have the following result: a count of 3 for Bob Jones, 1 for Ted Jones, and 1 for Ted Baker.
However, the difficulty is the third column 'collection'. I need to exclude duplicate names between collections, but not within collections. So we'd include all names in the count for the first collection, but only include names in the count from the second collection if they do NOT occur in the first collection.
So, the desired result would be as follows: a count of 2 for Bob Jones, 1 for Ted Jones, and 1 for Ted Baker.
first_name last_name collection included?
========================================== ===============
Bob Jones 1 Yes
Ted Jones 1 Yes
Bob Jones 1 Yes
Bob Jones 2 No
Ted Baker 2 Yes
I have really tried to get my head around this but I am starting to run out of ideas. Any help would be hugely appreciated... thanks!

Perhaps
SELECT first_name, last_name, COUNT( DISTINCT collection) AS cnt
FROM yourtable
GROUP BY first_name, last_name
The COUNT DISTINCT would eliminate the duplicate Bob/Jones/1 records.

Is this what you are expecting?
SELECT u1.first_name, u1.last_name, u1.collection FROM users u1
WHERE u1.collection = (SELECT min(u2.collection)
FROM users u2 WHERE u1.first_name = u2.first_name
AND u1.last_name = u2.last_name);
http://www.sqlfiddle.com/#!2/bd086/7

Related

Select rows where values in two columns not matching the request

I need to select all rows where value not matching on two columns
name | surname
John | Smith
John | Colch
John | Rak
Emmy | Oppo
John | Oppo
How can I select all the rows where name Name!=John and Surname!=Opp , so it would return everything except of last entry because when I try
Select * from t where name!='john' and surname!='oppo'
Then I'm loosing Emmy as she has the same surname.
I think you actually want OR logic here:
SELECT *
FROM t
WHERE name <> 'John' OR surname <> 'Oppo';

Select Distinct value Multiple Columns

This is my simplified table
year | teacher
1 | john
2 | john
2 | sam
3 | john
3 | simon
When I run the query below
SELECT year, teacher FROM table1 GROUP BY year
It gives me the result :
year | teacher
1 | john
2 | john
3 | john
In this case, year column is fine as it shows all distinct value, however teacher column is still repeated. I wish to have distinct values on teacher columns too.
Output I am looking for :
year | teacher
1 | john
2 | sam
3 | simon
This query is not valid SQL (even if MySQL happens to accept it):
SELECT year, teacher
FROM table1
GROUP BY year;
You need an aggregation function around teacher:
SELECT year, MAX(teacher)
FROM table1
GROUP BY year;
That said, this doesn't do what you want. That is hard to do in a single query. Instead, use two queries:
SELECT DISTINCT year FROM table1;
SELECT DISTINCT teacher FROM table1;

Count on the table MS access with c#

I have students records. If I get John repeats more than 2 times on my database, how can I count how many records John has on the database?
________________
Name | Grade
________________
John | F
Mo | A
John | F
I want to know how many F's John gets? I'm connecting this database with C#
Are you looking for this?
SELECT count(Grade),Name
FROM YourTable
GROUP BY Name
You will have to group on both Name and Grade:
SELECT
[Name],
Grade,
Count(*) As Achieved
FROM
YourTable
GROUP BY
[Name],
Grade

Removing redundant rows from db table

I have a database table like the following (bad design I know, but there are a ton of rows like this):
person1 | person2 | counselor
Jane Doe | John Doe | Mary Smith
John Doe | Jane Doe | Mary Smith
Frank Jones| Ann Jones | Tom Jones
Ann Jones | Frank Jones | Tom Jones
I'm trying to figure out how to just select one of the 'unique' rows so that a result would look like:
person1 | person2 | counselor
Jane Doe | John Doe | Mary Smith
Frank Jones| Ann Jones | Tom Jones
I've tried various things like SELECT distinct and SELECT MIN(person1), etc., but am striking out.
You will have 6 permutations of (person1,person2,counselor) and you can use union with all of them. Finally use a where clause so only one row per combination will be returned.
Fiddle with sample data
select * from (
select person1,person2,counselor
from tablename
union
select person1,counselor,person2
from tablename
union
select person2,person1,counselor
from tablename
union
select person2,counselor,person1
from tablename
union
select counselor,person2,person1
from tablename
union
select counselor,person1,person2
from tablename) t
where person1 < person2 and person2 < counselor
SQL Fiddle Demo
I include a case where no reverse duplicated and also another case where person1 = person2, also include P2.* in select just for debug.
SELECT P1.person1, P1.person2, P1.counselor, P2.*
FROM patient P1
LEFT JOIN patient P2
ON P1.person1 = P2.person2
AND P1.person2 = P2.person1
AND P1.counselor = P2.counselor
WHERE
concat(P1.person1, P1.person2) <= concat(P2.person1, P2.person2)
OR P2.person1 is null
When P2 is NULL mean there isn't a reverse combination of person1, person2
But when the combination exists only choose the smaller one as string concatenation.
With ranked_records AS
(
select *,
ROW_NUMBER() OVER(Partition By person1, person2, counselor
Order By person) [ranked]
from address
)
select * from ranked_records
where ranked > 1
For more detail, like how to delete latest records and keep the older one.
For MySql and if you have Id, try this:
DELETE A1
From Address A1
Where Exists (Select * From Address A2
Where A2.person1= A1.person1
AND A2.person2 = A1.person2
AND A2.counselor = A1.counselor
AND A1.AddressID > A2.AddressID)

SQL Using results of query to create another table

(SELECT childinfo.first,childinfo.last,COUNT(clubinfo.club) AS clubs_per_student FROM clubinfo
LEFT JOIN childinfo
ON childinfo.child_id=clubinfo.child_id
GROUP BY concat(studentinfo.first,' ',studentinfo.last)
)
Above is the query that I have written to combine the tables childinfo (containing the columns child_id, first name, and last name) and clubinfo (containing columns child_id and club). The above query would produce a table that is something like this:
first | last | sports_per_child
Sally | Jones | 2
Phil | Jones | 1
Jane | Doe | 1
John | Doe | 1
What I am looking to do is use the results of that query to produce a report of the total number of students who are in a particular number of clubs. So, for example, the table above would produce a report that there are 3 students that are in 1 club and 1 student that is in 2 clubs.
Any ideas on how to write a query that uses my previously written query as a subquery to accomplish this?
You just need to get a count and group by sports_per_child:
SELECT sports_per_child, count(*) FROM
(subquery) AS S
group by sports_per_child