I have a database table which stores competition entries from users.
I am wanting to select distinct email address, and then the number of entries for each email address. So I want to see how many times each email address has been used for entries.
I am thinking something along the lines of
SELECT DISTINCT `email` FROM `tablename` but have a count in there somewhere?
Sorry, probably a very basic question really. But I can't seem to get it.
Is this what you want?
SELECT email, COUNT(*) totalCount
FROM tableName
GROUP BY email
This will give you unique set of email and give you the total records for the specific email.
COUNT() is an aggregate function which basically count the number of records for each group if GROUP BY is specified, in this case email, but if no GROUP BY then it will count all records in the table.
CREATE TABLE tbl (`email` varchar(10));
INSERT INTO tbl (`email`)
VALUES
('a#b.com'),
('b#b.com'),
('c#b.com'),
('d#b.com'),
('e#b.com'),
('a#b.com'),
('b#b.com'),
('c#b.com'),
('c#b.com');
SELECT email, COUNT(*)
FROM tbl
GROUP BY email;
Result
| EMAIL | COUNT(*) |
----------------------
| a#b.com | 2 |
| b#b.com | 2 |
| c#b.com | 3 |
| d#b.com | 1 |
| e#b.com | 1 |
See a demo
Related
I have a table set up like this:
id | ip | name
---------------------------------
1 | 54.34.32.222 | John
2 | 23.44.64.843 | Rick
3 | 54.34.32.222 | John
4 | 23.44.64.843 | John
5 | 14.432.45.45 | Lisa
6 | 54.34.32.222 | Lisa
7 | 14.432.45.45 | Lisa
I only want to grab a unique IP per name. For example, "54.34.32.222" appears for John twice, so I only want to grab the first row. But "54.34.32.222" also appears for Lisa, so I would like to grab that IP as well.
The result should look something like this:
id | ip | name
---------------------------------
1 | 54.34.32.222 | John
2 | 23.44.64.843 | Rick
4 | 23.44.64.843 | John
5 | 14.432.45.45 | Lisa
6 | 54.34.32.222 | Lisa
How would you count the amount of times names appear? When doing so, it counts how many times the ip appears within the name, but I want the opposite.
SELECT MIN(id), COUNT(name), ip, name FROM yourTable GROUP BY ip, name
You never mentioned how you want to determine which record to retain in the case of duplicate ip-name pairs. However, based on your sample output it appears you are retaining the record with the smallest id value. In this case, we can just take the MIN(id) while grouping to get the desired result:
SELECT MIN(id), ip, name
FROM yourTable
GROUP BY ip, name
Follow the link below for a running demo:
SQLFiddle
This should work for you
SELECT min(id),ip,name FROM youTable group by ip,name
You would likely need to do a join against a derived table here to get what you want. You could also do as subselect, but I will show join solution, as for most use case it would be likely to perform better.
SELECT
yourtable.id AS id,
ip,
name
FROM yourtable
/* join regular table to a derived table
* where you have selected the first row id for each user
*/
INNER JOIN (
SELECT MIN(id)
FROM yourtable
GROUP BY name
) AS min_id_per_name
ON yourtable.id = min_id_per_name.id
ORDER BY yourtable.id
You could use the following query, which selects the lexical minimum of the IP address for any given name:
SELECT NAME, MIN(IP) AS IP
FROM TABLENAME
GROUP BY NAME
If you need the IP address corresponding to the first record found for that name (ie, the one on the record with the lowest ID):
SELECT NAME, IP
FROM TABLENAME TN
WHERE ID = (
SELECT MIN(ID)
FROM TABLENAME TN1
WHERE TN1.IP = TN.IP
AND TN1.NAME = TN.NAME
)
I have a MySQL table which has three columns:
Userid | Email | Points
---------------------------------------------------------
1 | jdoe#company.com | 20
2 | jdoe%40company.com | 25
3 | rwhite#company.com | 14
4 | rwhite%40company.com| 10
What I want to do is to delete duplicate email and merge points. I want my table to look like this:
Userid | Email | Points
---------------------------------------------------------
1 | jdoe#company.com | 45
3 | rwhite#company.com | 24
How would my query look like to return my desire table?
Anyone knows how to do this ?
Thanks in advance!
Are you looking for something like this?
SELECT MIN(userid) userid, email, SUM(points) points
FROM
(
SELECT userid, REPLACE(email, '%40', '#') email, points
FROM table1
) q
GROUP BY email
Output:
| USERID | EMAIL | POINTS |
|--------|--------------------|--------|
| 1 | jdoe#company.com | 45 |
| 3 | rwhite#company.com | 24 |
Here is SQLFiddle demo
Now if you want to deduplicate your table in-place you can do
-- Fix emails
UPDATE table1
SET email = REPLACE(email, '%40', '#')
WHERE email LIKE '%\%40%';
-- Merge points for duplicate records
UPDATE table1 t JOIN
(
SELECT email, SUM(points) points
FROM table1
GROUP BY email
HAVING COUNT(*) > 1
) q ON t.email = q.email
SET t.points = q.points;
-- Delete all duplicate records except ones with lowest `userid`
DELETE t
FROM table1 t JOIN
(
SELECT MIN(userid) userid, email
FROM table1
GROUP BY email
HAVING COUNT(*) > 1
) q ON t.email = q.email
WHERE t.userid <> q.userid;
Here is SQLFiddle demo
Use this query assuming you want to match email as is without any modification
SELECT MIN(user_id), SUM(points)as points, email FROM table_name GROUP BY email
We have a table called entries which stores user information against a date. Users are allowed to enter the database once per day. Some example data:
+----+------------------+----------+
| id | email | date |
+----+------------------+----------+
| 1 | marty#domain.com | 04.09.13 |
| 2 | john#domain.com | 04.09.13 |
| 3 | marty#domain.com | 05.09.13 |
+----+------------------+----------+
I need to work out how many times there are X entries with the same email in the database. For example, the result should look like this for the above data, where we have 1 instance of one entry and 1 instance of 2 entries:
+---------------+-------+
| times_entered | total |
+---------------+-------+
| 1 | 1 |
| 2 | 1 |
+---------------+-------+
I've tried a few things but the furthest I have been able to get is getting a count of the amount of times each email address was found. It seems like all I need to do from here is collate those results and perform another COUNT on those groups to get the totals, but I'm unsure of how I can do that.
Usually it can be something like
select times_entered, count(*) from
( select count(*) times_entered from entries group by email )
group by times_entered
Not sure if it works for MySQL though...
The following will get the number of records per email:
SELECT COUNT(1) AS times_entered, email
FROM entries
GROUP BY email
Therefore, using this query as a derived table, we can group by the number of records to get the count (we do not need to select the email column in the subquery because we don't care about it):
SELECT times_entered, COUNT(1) AS total
FROM
(
SELECT COUNT(1) AS times_entered
FROM entries
GROUP BY email
) x
GROUP BY times_entered
SQL Fiddle demo
SQL Fiddle demo with a slightly larger data set
It could be something like this:
SELECT times_entered, COUNT( times_entered ) AS total
FROM (
SELECT COUNT( email ) AS times_entered
FROM `entries`
WHERE 1
GROUP BY email
) AS tmp
GROUP BY times_entered;
Had a good read through similar topics but I can't quite a) find one to match my scenario, or b) understand others enough to fit / tailor / tweek to my situation.
I have a table, the important fields being;
+------+------+--------+--------+
| ID | Name | Price |Status |
+------+------+--------+--------+
| 1 | Fred | 4.50 | |
| 2 | Fred | 4.50 | |
| 3 | Fred | 5.00 | |
| 4 | John | 7.20 | |
| 5 | John | 7.20 | |
| 6 | John | 7.20 | |
| 7 | Max | 2.38 | |
| 8 | Max | 2.38 | |
| 9 | Sam | 21.00 | |
+------+------+--------+--------+
ID is an auto-incrementing value as records get added throughout the day.
NAME is a Primary Key field, which can repeat 1 to 3 times in the whole table.
Each NAME will have a PRICE value, which may or may not be the same per NAME.
There is also a STATUS field that need to be populated based on the following, which is actually the part I am stuck on.
Status = 'Y' if each DISTINCT name has only one price attached to it.
Status = 'N' if each DISTINCT name has multiple prices attached to it.
Using the table above, ID's 1, 2 and 3 should be 'N', whilst 4, 5, 6, 7, 8 and 9 should be 'Y'.
I think this may well involve some form of combination of JOINs, GROUPs, and DISTINCTs but I am at a loss on how to put that into the right order for SQL.
In order to get the count of distinct Price values per name, we must use a GROUP BY on the Name field, but since you also want to display all names ungrouped but with an additional Status field, we must first create a subselect in the FROM clause which groups by the name and determines whether the name has multiple price values or not.
When we GROUP BY Name in the subselect, COUNT(DISTINCT price) will count the number of distinct price values for each particular name. Without the DISTINCT keyword, it would simply count the number of rows where price is not null.
In conjunction with that, we use a CASE expression to insert N into the Status column if there is more than one distinct Price value for the particular name, otherwise, it will insert Y.
The subselect only returns one row per Name, so to get all names ungrouped, we join that subselect to the main table on the condition that the subselect's Name = the main table's Name:
SELECT
b.ID,
b.Name,
b.Price,
a.Status
FROM
(
SELECT Name, CASE WHEN COUNT(DISTINCT Price) > 1 THEN 'N' ELSE 'Y' END AS Status
FROM tbl
GROUP BY Name
) a
INNER JOIN
tbl b ON a.Name = b.Name
Edit: In order to facilitate an update, you can incorporate this query using JOINs in the UPDATE like so:
UPDATE
tbl a
INNER JOIN
(
SELECT Name, CASE WHEN COUNT(DISTINCT Price) > 1 THEN 'N' ELSE 'Y' END AS Status
FROM tbl
GROUP BY Name
) b ON a.Name = b.Name
SET
a.Status = b.Status
Assuming you have an unfilled Status column in your table.
If you want to update the status column, you could do:
UPDATE mytable s
SET status = (
SELECT IF(COUNT(DISTINCT price)=1, 'Y', 'N') c
FROM (
SELECT *
FROM mytable
) s1
WHERE s1.name = s.name
GROUP BY name
);
Technically, it should not be necessary to have this:
FROM (
SELECT *
FROM mytable
) s1
but there is a mysql limitation that prevents you to select from the table you're updating. By wrapping it in parenthesis, we force mysql to create a temporary table and then it suddenly is possible.
I did take a look in and outside of SO and still don't know if this can be done. I have a table that looks like this:
User ID | Role | First Name | Last Name | Email |<br>
0001 | K | John | Smith | e#e.co|<br>
0002 | Q | Jane | Dickens | q#q.co|<br>
0003 | K | John | Smith | e#e.co|<br>
0004 | J | Jack | Paper | j#j.co|<br>
As you can see, the table contains a duplicate due to a user entering their information two separate times. I want to display the rows that
1. have the same first name
2. have the same last name
3. have the same email
4. do NOT have the same User ID
I can get the first three conditions to work with an inner join subquery, but I get 0 returned results when ever I try to to add in the fourth condition.
Thanks in advance for your help!
SELECT GROUP_CONCAT(`User ID`) as IDs, Role, `First Name`, `Last Name`, Email
FROM users_table
GROUP BY Role,`First Name`,`Last Name`,Email
Will give a table like
IDs | Role | First Name | Last Name | Email |
0001,0003 | K | John | Smith | e#e.co|
0002 | Q | Jane | Dickens | q#q.co|
0004 | J | Jack | Paper | j#j.co|
The trick is to GROUP BY everything except ID.
You could also do:
SELECT COUNT(`User ID`) as numIDs, GROUP_CONCAT(`User ID`) as IDs,
Role, `First Name`, `Last Name`, Email
FROM users_table
GROUP BY Role,`First Name`,`Last Name`,Email
HAVING numIDs > 1
to get
numIDs |IDs | Role | First Name | Last Name | Email |
2 |0001,0003 | K | John | Smith | e#e.co|
Anyhow, you get the point of how to vary it to your purposes.
Try something like:
select *
from tb_users
where (first_name, last_name, email) in
(select first_name, last_name, email
from tb_users
group by first_name, last_name, email
having count(*) > 1)
I am assuming that your table does not contain true duplicate rows (where the User ID also matches). I think it should be as simple as this to get the relevant rows back (with my adjusted column and table naming scheme):
SELECT ui.user_id, ui.role, ui.first_name, ui.last_name, ui.email
FROM user_info AS ui
INNER JOIN user_info AS udi
ON ui.first_name = udi.first_name
AND ui.last_name = udi.last_name
AND ui.email = udi.email
AND ui.user_id != udi.user_id;
I would use count(*) and group by clause.
Like this
SELECT count(*) as count FROM table group by concat(firstname,'\n',last_name) having count=1;
I think you want to delete duplicate rows. Only take count by group by and delete duplicate rows.
select * from tb_users
group by first_name, last_name, email
having count(*) > 1
You don't have to download extensions; go left bottom corner, click settings, click Keyboard Shortcuts, and search "duplication". You should see as in the below image and assign the key combination you want. I choose shift+D because I don't want to lose the current behavior of ctrl+D it is also very beneficial.