From SELECT to UPDATE in MySQL - mysql

I would like you to help me with this, I have a little problem with this, but I don't know how I can fix it, basically I want to update the so called duplicatedusernameid, and update it into the users database. Here is my code:
UPDATE users SET duplicatedusernameid = (SELECT CONCAT(first_name,middle_name,last_name)
,COUNT(*)-1 AS duplicatedusernameid HAVING COUNT(*) > 1) WHERE id = 1
And here is the working SELECT function, but instead of select I want UPDATE, like the one above, but that one doesn't work. Here is the SELECT code:
SELECT CONCAT(first_name,middle_name,last_name),COUNT(*)-1 AS duplicatedusernameid
FROM users HAVING COUNT(*) > 1
So basically I want to get the value of the duplicatedusernameid and update it.

You can use a SQL statement like this:
update users a
inner join (
-- get the count for a user
SELECT first_name, middle_name, last_name, COUNT(*)-1 AS duplicatedusernameid
from users
group by first_name, middle_name, last_name
) b
on a.first_name = b.first_name
and a.middle_name = b.middle_name
and a.last_name = b.last_name
set a.duplicatedusernameid = b.duplicatedusernameid
where a.id = 1;
Table
create table users (
id int,
first_name varchar(100),
middle_name varchar(100),
last_name varchar(100),
duplicatedusernameid varchar(100)
);
insert into users (id, first_name, middle_name, last_name) values
(1, 'John', '', 'Smith'),
(2, 'John', '', 'Smith'),
(3, 'Jessie', '', 'Marcus'),
(4, 'Jessie', '', 'Marcus'),
(5, 'Jessie', '', 'Marcus'),
(6, 'Don', '', 'Kassieth');
Results (if you remove the where clause)
| id | first_name | middle_name | last_name | duplicatedusernameid |
|----|------------|-------------|-----------|----------------------|
| 1 | John | | Smith | 1 |
| 2 | John | | Smith | 1 |
| 3 | Jessie | | Marcus | 2 |
| 4 | Jessie | | Marcus | 2 |
| 5 | Jessie | | Marcus | 2 |
| 6 | Don | | Kassieth | 0 |
Explanation
SELECT first_name, middle_name, last_name, COUNT(*)-1 AS duplicatedusernameid
from users
group by first_name, middle_name, last_name
The above SQL statement will get the count for each unique first, middle and last name combination. You can shortlist this by adding having count(*) > 1 below the group by clause.
We then join users table with this count-related table based on first, middle and last name combination. Wherever there is a match, update the retrieved count in the users table.
SQLFiddle
http://sqlfiddle.com/#!9/c43ea/1

Related

How to join 2 tables with one of them containing multiple values in a single column

I have two tables users and interests which i'm trying to join. Inside users table i have columns as id, name, interest, etc. The interest column contain multiple values as "1,2,3". My second table interests have 2 columns id and name as:
id | name
-------------
1 | business
2 | farming
3 | fishing
What i want to do is join interests table with users table so i get the following output:
users table:
id | name | interest | interest_name
----------------------------------------------
1 | username | "1,2" | "business, farming"
2 | username | "2,3" | " farming, fishing"
I wrote the following query to achieve this:
select users.*, interests.name as interest_name
from users
left join interests on users.interest = interests.id;
Results i got:
id | name | interest | interest_name
----------------------------------------
1 | username | "1,2" | "business"
2 | username | "2,3" | " farming"
Problem:
I'm only getting the name of first values from interest column whereas i want all the values from interest column i have already tried using group_concat and find_in_set but getting the same results.
In the case you cannot create an additional database table in order to normalize the data...
Here's a solution that creates an ad hoc, temporary user_interests table within the query.
SELECT users.id user_id, username, interests, interests.interest
FROM users
LEFT JOIN (
SELECT
users.id user_id,
(SUBSTRING_INDEX(SUBSTRING_INDEX(users.interests, ',', ui.ui_id), ',', -1) + 0) ui_id
FROM users
LEFT JOIN (SELECT id AS ui_id FROM interests) ui
ON CHAR_LENGTH(users.interests) - CHAR_LENGTH(REPLACE(users.interests, ',', '')) >= (ui.ui_id - 1)
) user_interests ON users.id = user_interests.user_id
LEFT JOIN interests ON user_interests.ui_id = interests.id
ORDER BY user_id, ui_id;
Outputs:
user_id | username | interest_ids | interest
--------+----------+--------------+---------
1 | fred | 3,4,8,6,10 | fishing
1 | fred | 3,4,8,6,10 | sports
1 | fred | 3,4,8,6,10 | religion
1 | fred | 3,4,8,6,10 | science
1 | fred | 3,4,8,6,10 | philanthropy
2 | joe | 7,11,8,9 | art
2 | joe | 7,11,8,9 | science
2 | joe | 7,11,8,9 | politics
2 | joe | 7,11,8,9 | cooking
As you can see...
SELECT
users.id user_id,
(SUBSTRING_INDEX(SUBSTRING_INDEX(users.interests, ',', ui.ui_id), ',', -1) + 0) ui_id
FROM users
LEFT JOIN (SELECT id AS ui_id FROM interests) ui
ON CHAR_LENGTH(users.interests) - CHAR_LENGTH(REPLACE(users.interests, ',', '')) >= (ui.ui_id - 1)
...builds and populates the temporary table user_interests with the users.interests field data normalized:
user_id | ui_id
--------+------
1 | 3
1 | 4
1 | 6
1 | 8
1 | 10
2 | 7
2 | 8
2 | 9
2 | 11
...which is then LEFT JOIN'ed between the users and interests tables.
Try it here: https://onecompiler.com/mysql/3yfhmgq3y
-- create
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(20),
interests VARCHAR(20)
);
CREATE TABLE interests (
id INT PRIMARY KEY,
interest VARCHAR(20)
);
-- insert
INSERT INTO users VALUES (1, 'fred', '3,4,8,6,10'), (2, 'joe', '7,11,8,9');
INSERT INTO interests VALUES (1, 'business'), (2, 'farming'), (3, 'fishing'), (4, 'sports'), (5, 'technology'), (6, 'religion'), (7, 'art'), (8, 'science'), (9, 'politics'), (10, 'philanthropy'), (11, 'cooking');
-- select
SELECT users.id user_id, username, interests, interests.interest
FROM users
LEFT JOIN (
SELECT
users.id user_id,
(SUBSTRING_INDEX(SUBSTRING_INDEX(users.interests, ',', ui.ui_id), ',', -1) + 0) ui_id
FROM users
LEFT JOIN (SELECT id AS ui_id FROM interests) ui
ON CHAR_LENGTH(users.interests) - CHAR_LENGTH(REPLACE(users.interests, ',', '')) >= (ui.ui_id - 1)
) user_interests ON users.id = user_interests.user_id
LEFT JOIN interests ON user_interests.ui_id = interests.id
ORDER BY user_id, ui_id;
Inspired by Leon Straathof's and fthiella's answers to this SO question.
Pull the interest column out of the users table and create a user_interests table that contains the user ids and interest ids:
user_id | interest_id
--------+------------
1 | 1
1 | 2
2 | 2
2 | 3
Then join the users table to the user_interests table, and the user_interests table to the interests table:
SELECT users.username, interests.interest
FROM users
LEFT JOIN user_interests ON users.id = user_interests.user_id
LEFT JOIN interests ON user_interests.interest_id = interests.id
WHERE interest_id IS NOT NULL;
Outputs:
username | interest
---------+---------
Clark | business
Clark | farming
Dave | farming
Dave | fishing
Then use your server programming language to compile the query results.
Try it here: https://onecompiler.com/mysql/3yfe5pp7x
-- create
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username TEXT NOT NULL
);
CREATE TABLE user_interests (
user_id INTEGER,
interest_id INTEGER,
UNIQUE KEY user_interests_constraint (user_id,interest_id)
);
CREATE TABLE interests (
id INTEGER PRIMARY KEY,
interest TEXT NOT NULL
);
-- insert
INSERT INTO users VALUES (1, 'Clark'), (2, 'Dave'), (3, 'Ava');
INSERT INTO interests VALUES (1, 'business'), (2, 'farming'), (3, 'fishing');
INSERT INTO user_interests VALUES (1, 1), (1, 2), (2, 2), (2, 3);
-- fetch
SELECT users.username, interests.interest
FROM users
LEFT JOIN user_interests ON users.id = user_interests.user_id
LEFT JOIN interests ON user_interests.interest_id = interests.id
WHERE interest_id IS NOT NULL;

MySQL query not giving results as expected

Below are two mysql tables. I want to check if the two people are in teams from Table: Teams and then getting their name and email from Table: Registration. I am having a hard time writing a mysql query for it.
Table: Registration
id: 1 name:jason email:jason#xyz.com
id: 2 name:kim email:kim#xyz.com
id: 3 name:tim email:tim#xyz.com
Table:Teams
team_id: 1 person1Id: 1 person2Id: 2
team_id: 2 person1Id: 1 person2Id: 3
You have to join the registration table twice and give them a unique alias
Schema (MySQL v8.0)
CREATE TABLE Teams (
`team_id` INTEGER,
`person1Id` VARCHAR(9),
`person2Id` INTEGER
);
INSERT INTO Teams
(`team_id`, `person1Id`, `person2Id`)
VALUES
('1', '1', '2'),
('1', '1', '3');
CREATE TABLE Registration (
`id` INTEGER,
`name` VARCHAR(5),
`email` VARCHAR(13)
);
INSERT INTO Registration
(`id`, `name`, `email`)
VALUES
('1', 'jason', 'jason#xyz.com'),
('2', 'kim', 'kim#xyz.com'),
('3','tim','tim#xyz.com');
Query #1
SELECT
t.team_id,r1.name,r1.email,r2.name,r2.email
FROM Teams t
INNER JOIN Registration r1 ON t.person1Id = r1.id
INNER JOIN Registration r2 ON t.person2Id = r2.id;
| team_id | name | email | name | email |
| ------- | ----- | ------------- | ---- | ----------- |
| 1 | jason | jason#xyz.com | kim | kim#xyz.com |
| 1 | jason | jason#xyz.com | tim | tim#xyz.com |
View on DB Fiddle
you can select both ids from Teams table and use in clause to get name and email from Registration table as
select name, email from Registration where id in(select person1Id, person2Id from Teams where team_id=1)

Find duplicate values within 3 columns SQL

I have a table like the below:
Site | Name | ID
A | Mike | 1
A | Mary | 2
A | Mary | 3
B | Mary | 1
B | Rich | 2
I'd like to find all the duplicate Name's within a Site. So I'm trying to return:
Site | Name | ID
A | Mary | 2
A | Mary | 3
I've tried this:
SELECT DISTINCT Site, Name, ID
from table
group by ID having count(*) > 1
The results come back erroneously because it's counting Sites A & B together. I would like to only find the duplicates for within each Site--not duplicates across Sites.
You can use exists or in:
select t.*
from t
where exists (select 1
from t t2
where t2.site = t.site and t2.name = t.name and t2.id <> t.id
);
You can try to use NOT exists with subquery having.
the duplicate Name's within a Site
CREATE TABLE T(
Site varchar(5),
Name varchar(5),
ID int
);
insert into t values ('A','Mike', 1);
insert into t values ('A','Mary', 2);
insert into t values ('A','Mary', 3);
insert into t values ('B','Mary', 1);
insert into t values ('B','Rich', 2);
Query 1:
SELECT * FROM T t1 WHERE
NOT exists
(
SELECT 1
FROM T tt
where t1.name = tt.name
group by Name
HAVING MIN(tt.ID) = t1.ID
)
Results:
| Site | Name | ID |
|------|------|----|
| A | Mary | 2 |
| A | Mary | 3 |
find the duplicates for within each Site
CREATE TABLE T(
Site varchar(5),
Name varchar(5),
ID int
);
insert into t values ('A','Mike', 1);
insert into t values ('A','Mary', 2);
insert into t values ('A','Mary', 3);
insert into t values ('B','Mary', 1);
insert into t values ('B','Rich', 2);
Query 1:
SELECT t1.*
FROM T t1
WHERE not exists
(
SELECT 1
FROM T tt
where t1.name = tt.name and t1.Site = tt.Site
group by Name,Site
HAVING MIN(tt.ID) = t1.ID
)
Results:
| Site | Name | ID |
|------|------|----|
| A | Mary | 3 |

MySQL query eleminating duplicates from second table

I have two mysql tables: table_1 and table_2.
table_1:
| c_id | name | email |
| 1 | tom | t#t.com |
table_2:
| a_id | c_id | address | street |
| 1 | 1 | 67 | home |
| 2 | 1 | 68 | main |
How to create mysql query that will select table_1.name, table_1.email, table_2.address and table_2.street returning only one record like:
| name | email | address | street |
| tom | t#t.com | 67 | home |
Thanks for any suggestion.
Regards, T
Try this:
SELECT table_1.name, table_1.email, table_2.address, table_2.street
FROM table_1
JOIN table_2
ON table_1.c_id = table_2.c_id
GROUP BY table_1.c_id
SQLfiddle demo
The GROUP BY will determine which column you want to use to group the results by. B.T.W. if you like the change the column head you can add AS followed by the column head name (table_1.name AS "First name").
Table structure and sample data:
CREATE TABLE table_1
(`c_id` int, `name` varchar(3), `email` varchar(7))
;
INSERT INTO table_1
(`c_id`, `name`, `email`)
VALUES
(1, 'tom', 't#t.com')
;
CREATE TABLE table_2
(`a_id` int, `c_id` int, `address` int, `street` varchar(4))
;
INSERT INTO table_2
(`a_id`, `c_id`, `address`, `street`)
VALUES
(1, 1, 67, 'home'),
(2, 1, 68, 'main')
;
If you like to limit the sql query to a certain person say tom WHERE table_1.name LIKE 'Tom'. Like so:
SELECT table_1.name, table_1.email, table_2.address, table_2.street
FROM table_1
JOIN table_2
ON table_1.c_id = table_2.c_id
WHERE table_1.name LIKE 'Tom'
GROUP BY table_1.c_id;
You can also use = but with LIKE you can use wildcards like T%
you should use the SQL statement LEFT JOIN, for example
SELECT name, email, address, street
FROM table1
LEFT JOIN table2
ON table1.c_id=table2.c_id;
with the possible option WHERE name = 'tom'
select table_1.name as name, table_1.email as email, table_2.address as address, table_2.street as street
from table_1
left join table_2 on table_1.c_id = table_2.c_id

How to select from separate subclasses' tables?

I have a pretty simple database. The idea is that Student and Teacher both inherit from "Person" which is made of id and name.
create table Student (
id int,
name text,
year int
);
create table Teacher (
id int,
name text,
department varchar(15)
);
insert into Student (id, name, year) values
(1, 'herper', 2007),
(2, 'derpins', 2010);
insert into Teacher (id, name, department) values
(3, 'skerp', 'csc');
I'm trying to make a select statement that will return this:
id name year department
1 'herper' 2007 NULL
2 'derpins' 2010 NULL
3 'skerp' NULL 'csc'
This is the closest I've gotten:
select *
from Student
union
select * from Teacher;
Any ideas? Thanks!
SELECT id, name, year, NULL department
FROM Student
UNION
SELECT id, name, NULL, department
FROM Teacher;
Output:
| ID | NAME | YEAR | DEPARTMENT |
--------------------------------------
| 1 | herper | 2007 | (null) |
| 2 | derpins | 2010 | (null) |
| 3 | skerp | (null) | csc |
SQLFiddle