I have duplicate entries due to a programming error.
Table Example:
id | group | userNum | username | name
---------------------------------------
1 | AA11 | D-01 | user1 | Donald
2 | AA11 | D-02 | user2 | Cruz
3 | AA11 | D-03 | user3 | Rubio
4 | AA11 | D-01 | user1 | Donald <------DUPLICATE
5 | AA11 | D-04 | user4 | Cruz
6 | AA22 | D-03 | user2 | Rubio
7 | AA22 | D-02 | user1 | Donald
userNum, username must be unique to each group, but a group can have userNum, username, name which are found in other groups.
A standard SQL approach is to use a subquery in the WHERE clause. For instance:
delete from example
where id not in (select min(id)
from example e2
group by group, userNum, username, name
);
This doesn't work in MySQL. You can do something similar using left join:
delete e
from example e left join
(select min(id) as minid
from example e2
group by group, userNum, username, name
) ee
on e.id = ee.minid
where ee.minid is null;
Add group by userNum, username, group at the end of your query..
Related
I have this 2 tables
1st Table "Users"
+----+-----------+----------+
| ID | FirstName | LastName |
+----+-----------+----------+
| 1 | Jeff | Bezos |
| 2 | Bill | Gates |
| 3 | Elon | Musk |
+----+-----------+----------+
2nd Table "Records"
+----+--------+------------+
| ID | IDUser | RecordDate |
+----+--------+------------+
| 1 | 1 | 15/06/2021 |
| 2 | 2 | 05/06/2021 |
| 3 | 2 | 12/06/2021 |
| 4 | 2 | 02/06/2021 |
| 5 | 1 | 17/06/2021 |
+----+--------+------------+
So this 2 tables are linked each other by using a Foreing key Records.IDUsers -> Users.ID
I wanted to make a query that does this
+-----------+----------+----------------+--------------------+
| FirstName | LastName | Lastest Record | Numbers of Records |
+-----------+----------+----------------+--------------------+
| Jeff | Bezos | 17/06/2021 | 2 |
| Bill | Gates | 12/06/2021 | 3 |
| Elon | Musk | NULL | NULL |
+-----------+----------+----------------+--------------------+
You need to use LEFT JOIN in order to get back users without records too; then the MAX and COUNT aggregate functions.
First version: This will return 0 for the number of records instead of NULL, when there are no records for a specific user. Latest record will be NULL as expected.
SELECT
FirstName,
LastName,
MAX(RecordDate) AS LatestRecord,
COUNT(Records.ID) AS NumberOfRecords
FROM Users LEFT JOIN Records on Users.ID = Records.IDUser
GROUP BY Users.ID;
If you want NULL instead of 0 (which normally you do not want), you can use the IF function like this:
SELECT
FirstName,
LastName,
MAX(RecordDate) AS LatestRecord,
IF(COUNT(Records.ID) > 0, COUNT(Records.ID), NULL) AS NumberOfRecords
FROM Users LEFT JOIN Records on Users.ID = Records.IDUser
GROUP BY Users.ID;
Second version: It might happen that running the above query will return an error, something like:
Error: ER_WRONG_FIELD_WITH_GROUP: ...; this is incompatible with sql_mode=only_full_group_by
This happens when/if the ONLY_FULL_GROUP_BY SQL mode is enabled (which it is by default since MySQL 5.7.5). In order to get around this error, you can use the ANY_VALUE function to select the nonaggregated fields:
SELECT
ANY_VALUE(FirstName) AS FirstName,
ANY_VALUE(LastName) AS LastName,
MAX(RecordDate) AS LatestRecord,
COUNT(Records.ID) AS NumberOfRecords
FROM Users LEFT JOIN Records on Users.ID = Records.IDUser
GROUP BY Users.ID;
left join select all user even if does not have records
select * from users left join records on records.IDUser = ID;
I have two tables in my MySQL database.
The first one stores a list of users, and the other, stores a list of contacts for each user.
Users table:
+----+----------+--------------+
| id | name | phoneNumber |
+----+----------+--------------+
| 1 | David | 661-618-5436 |
| 2 | Sarah | 818-526-4830 |
| 3 | Suzan | 323-623-3493 |
+----+----------+--------------+
Contacts table:
+----+-----------------+--------+--------------+
| id | belongsToUserId | name | phoneNumber |
+----+-----------------+--------+--------------+
| 1 | 1 | Gerard | +18185329384 |
| 2 | 1 | Austin | +18739283847 |
| 3 | 2 | Jamie | +15655468907 |
| 4 | 2 | Jade | +19893828192 |
| 5 | 3 | Phil | +18786754234 |
| 6 | 3 | Duke | +18765467832 |
| 7 | 3 | Gerard | +18185329384 |
| 8 | 3 | Jade | +19893828192 |
+----+-----------------+--------+--------------+
What I want to do, is create a query that efficiently takes 2 user IDs and returns the common contacts by phoneNumber for these two users.
For example: User IDs 1 & 3 both have Gerard | +18185329384 in their contacts so the query will return only him.
What could be the most efficient query for this kind of task?
Thanks :)
If I understood your question correctly, I think this might be what you're looking for:
SELECT
c1.id,
c1.belongsToUserId,
c1.phoneNumber,
c1.name
FROM
Contacts c1
JOIN
Contacts c2 ON (c1.phoneNumber=c2.phoneNumber AND c2.userId=3)
WHERE
c1.belongsToUserId =1
You want a self-join:
select c1.name, c1.phonenumber
from contacts c1 join
contacts c2
on c1.name = c2.name and c1.phonenumber = c2.phonenumber and
c1.belongsToUserId = 1 and
c2.belongsToUserId = 3;
The following SELECT will give you all contacts who has more than 1 User.
SELECT Contacts.name, Contacts.phoneNumber
FROM Users INNER JOIN Contacts ON (Users.id = Contacts.belongsToUserId)
GROUP BY Contacts.name, Contacts.phoneNumber
HAVING COUNT (*) > 1
Following query will display shared contact along with the UseID who's having common contacts.
If you just want to show details of shared contacts, then you can skip first 2 columns.
select min(belongsToUserId) as User1,
max(belongsToUserId) as User2,
name,
phone Number
from contacts
group by name,phoneNumber
having count(*) > 1;
SELECT
cp.name,
cs.phoneNumber
FROM
Contacts cp
INNER JOIN Contacts cs ON
cp.name = cs.name AND cp.phoneNumber = cs.phoneNumber
AND
cp.belongsToUserId IN ( 1,3 );
I have two mysql tables as follows:
contacts
---------------
id | name | email
---------------
1 | Jack | jack#test.com
2 | John | john#test.com
3 | Liz | liz#test.com
5 | Jack | jack#test.com
6 | Liz | liz#test.com
7 | Mike | mike#test.com
8 | Jack | jack#test.com
purchases
-------------------
id | contact_id | paid
-------------------
1 | 3 | true
2 | 5 | true
I need unique contact_ids that made purchase and other unique contact_ids that don't have made purchases.
So the final result will be as:
-------------------
id | name | email
------------------
2 | John | john#test.com
3 | Liz | liz#test.com
5 | Jack | jack#test.com
7 | Mike | mike#test.com
I tried the query as:
SELECT * FROM contacts LEFT JOIN purchases ON contacts.id = purchases.user_id
But this is not giving me unique rows as required. I tried several combination of DISTINCT, but I am not getting the result as required.
did you try this?
SELECT COALESCE(purchases.contact_id, contacts.id) as id, name, email
FROM contacts
LEFT JOIN purchases ON contacts.id = purchases.user_id
GROUP BY name
SQL FIDDLE
Something like that should work, but its performance is "?".
SELECT * FROM contacts WHERE id IN (
SELECT DISTINCT id as i FROM purchases
UNION
SELECT DISTINCT contact_id as i FROM purchases
)
GROUP BY id
I have a MySQL table which has the following data.
surveyid | staff | username | ipaddress | rating | comments
---------|--------|----------|-----------|---------|----------
0 | staff1 | user1 | 1.1.1.1 | 10 | none
1 | staff2 | user2 | 1.2.1.1 | 5 | none
2 | staff2 | user3 | 1.2.1.1 | 10 | none
3 | staff2 | user2 | 1.2.1.1 | 6 | none
4 | staff3 | user4 | 1.1.1.51 | 10 | none
5 | staff4 | user3 | 1.21.12.1 | 9 | none
6 | staff5 | user2 | 1.12.1.1 | 10 | none
I am wanting a query that will select surveyid, staff, username and ipaddress only when an ipaddress has been used for multiple users for the same staff.
Basicly I am wanting to find out what staff has multiple users submit off the same ip address.
I have tried the following but it does not work.
SELECT * FROM `comment_data` CD
INNER JOIN
(SELECT `ipaddress`, COUNT(DISTINCT `staff`)
FROM `comment_data` GROUP BY `ipaddress` HAVING COUNT(DISTINCT `staff`) > 1 )
USECOUNT ON USECOUNT.`ipaddress` = CD.`ipaddress`
I also tried the following query.
SELECT * FROM `commend_data` WHERE `staff`+`ipaddress` IN
(SELECT `staff`+`ipaddress` FROM `comment_data` GROUP BY `staff`, `ipaddress`
HAVING COUNT(`surveyid`) > 1)
Also I want to make sure I display all duplicates and I don't want to display just counts.
If you need any more information please ask.
Thanks
Paul
select surveyid, staff, username, ipaddress
from table1
where ipaddress+staff in
(
select ipaddress+staff
from table1
group by ipaddress,staff
having count(surveyid)>1
)
SQL FIDDLE
SELECT surveyid,
PT.staff,
username,
PT.ipaddress
FROM PaulTable PT
INNER JOIN
(
SELECT ipaddress, staff
FROM PaulTable
GROUP BY ipaddress, staff
HAVING COUNT(DISTINCT username) > 1
) USECOUNT
ON USECOUNT.ipaddress = PT.ipaddress
AND USECOUNT.staff = PT.staff
I would like to ask a quick question regarding a mysql query.
I have a table named trans :
+----+---------------------+------+-------+----------+----------+
| ID | Date | User | PCNum | Customer | trans_In |
+----+---------------------+------+-------+----------+----------+
| 8 | 2013-01-23 16:24:10 | test | PC2 | George | 10 |
| 9 | 2013-01-23 16:27:22 | test | PC2 | Nick | 0 |
| 10 | 2013-01-24 16:28:48 | test | PC2 | Ted | 10 |
| 11 | 2013-01-25 16:36:40 | test | PC2 | Danny | 10 |
+----+---------------------+------+-------+----------+----------+
and another named customers :
+----+---------+-----------+
| ID | Name | Surname |
+----+---------+-----------+
| 1 | George | |
| 2 | Nick | |
| 3 | Ted | |
| 4 | Danny | |
| 5 | Alex | |
| 6 | Mike | |
.
.
.
.
+----+---------+-----------+
I want to view the sum of trans_in column for specific customers in a date range BUT ALSO include in the result set, those customers that haven't got any records in the selected date range. Their sum of trans_in could appear as NULL or 0 it doesn't matter...
I have the following query :
SELECT
`Date`,
Customer,
SUM(trans_in) AS 'input'
FROM trans
WHERE Customer IN('George','Nick','Ted','Danny')
AND `Date` >= '2013-01-24'
GROUP BY Customer
ORDER BY input DESC;
But this will only return the sum for 'Ted' and 'Danny' because they only have transactions after the 24th of January...
How can i include all the customers that are inside the WHERE IN (...) function, even those who have no transactions in the selected date range??
I suppose i'll have to join them somehow with the customers table but i cannot figure out how.
Thanks in advance!!
:)
In order to include all records from one table without matching records in another, you have to use a LEFT JOIN.
SELECT
t.`Date`,
c.name,
SUM(t.trans_in) AS 'input'
FROM customers c LEFT JOIN trans t ON (c.name = t.Customer AND t.`Date` >= '2013-01-24')
WHERE c.name IN('George','Nick','Ted','Danny')
GROUP BY c.name
ORDER BY input DESC;
Of course, I would mention that you should be referencing customer by ID, and not by name in your related table. Your current setup leads to information duplication. If the customer changes their name, you now have to update all related records in the trans table instead of just in the customer table.
try this
SELECT
`Date`,
Customer,
SUM(trans_in) AS 'input'
FROM trans
inner join customers
on customers.Name = trans.Customer
WHERE Customer IN('George','Nick','Ted','Danny')
GROUP BY Customer
ORDER BY input DESC;