I have a large table with data that is not unique but needs to be. This table is a result of multiple union selects so is not an actual table. I cannot make it an actual table for other reasons.
All of the UNION'd tables have an email column which will eventually be unique. The resulting records look like this:
1 ozzy#test.com Ozzy
2 test#test.com Tony
3 test#yahoo.com Steve
4 tiny#test.com
13 tony#gmail.com Tony
14 test#test.com Ozzy
15 test#yahoo.com Dave
16 tiny#test.com Tim
As you can see, some emails appear more then once with different names or non-existent names. When I add a GROUP BY email clause at the end, the results look like this:
1 ozzy#test.com Ozzy
2 test#test.com Tony
3 test#yahoo.com Steve
4 tiny#test.com
13 tony#gmail.com Tony
As you can see, email 4 does not have a name because it chose the first entry with NULL for a name. Then I tried to use GROUP_CONCAT which made the results look like this:
1 ozzy#test.com Ozzy
14 test#test.com Ozzy,Tony
15 test#yahoo.com Dave,Steve
16 tiny#test.com Tim
13 tony#gmail.com Tony
As you can see, now everyone has a name but some rows have more then one name concatenated. What I want to do is GROUP BY email and choose the first NOT NULL entry of each column for each row to theoretically look like so:
1 ozzy#test.com Ozzy
2 test#test.com Tony
3 test#yahoo.com Steve
4 tiny#test.com Tim
13 tony#gmail.com Tony
I have tried using COALESCE but it doesn't work as intended. My current query looks like so:
SELECT
id,
email,
`name`
FROM
(
SELECT
email,
`name`
FROM
multiple_tables_and_unions
) AS emails
GROUP BY email
I have removed the code from the temporary table as it contains many tables but all select the email and name column. Essentially I need a function like GROUP_COALESCE but unfortunately it does not exist. What are my options?
Try using MAX, like this:
SELECT
email,
MAX(`name`)
FROM
(
SELECT
email,
`name`
FROM
multiple_tables_and_unions
) AS emails
GROUP BY email
To select the first non null value, GROUP_CONCAT can be handy here. Below is the example:
SELECT
email,
SUBSTRING_INDEX(GROUP_CONCAT(`name`), ',',1)
FROM
(
SELECT
email,
`name`
FROM
multiple_tables_and_unions
) AS emails
GROUP BY email;
Related
For example, let us consider this table:
In this image consists of rows of 8 where names like Mike,Glenn,Daryl,Shane and Patricia is included with their respective ages
Id
Name
Age
1
Mike
25
2
Glenn
19
3
Glenn
19
4
Daryl
56
5
Shane
30
6
Shane
30
7
Patricia
16
Now I want to insert the type of query that will show the names without repetitions like This, not like This
EDIT: I entered the data from first picture. The request is to list the names without duplicates, as shown in the second and third picture but I will not convert them to text.
DISTINCT specifies removal of duplicate rows from the result set.
SELECT DISTINCT Name
FROM tablename
see: use DISTINCT in SELECT
You can use GROUP BY to achieve it.
SELECT * FROM your_table
GROUP BY your_table.name
ORDER BY id
With the data you gave, the result from this query will be:
id
name
age
1
Mike
25
2
Glenn
19
4
Deryl
56
5
Shane
30
7
Patricia
16
Duplicate values can be found using this
SELECT email, COUNT(email)
FROM users
GROUP BY email
HAVING COUNT(email) > 1
for the data
ID NAME EMAIL
1 John asd#example.com
2 Sam asd#example.com
3 Tom asd#example.com
4 Bob bob#example.com
5 mob bob#example.com
But the table I need is
NAME EMAIL
John, Sam, Tom asd#example.com
Bob, mob bob#example.com
You need the GROUP_CONCAT() function, which IIRC works in both MySql and Sqlite, but handles NULL values different between the two (I may be wrong on that last part).
SELECT group_concat(name) as Name, email
FROM users
GROUP BY email
HAVING COUNT(email) > 1
I have a table of users and a table of electronic signatures - I want to be able to show for a given document who has signed and who has not.
Lets say we have employees:
EID Name
1 Bob
2 Tom
3 Fred
signatures:
EID Document Signature
1 1 Bob
1 2 Bob
1 3 Bob
2 1 Tom
3 2 Fred
My issue is that I can get this to work fine for document 4 - as no one has signed I can look where the document is null
However, if I look for document 2, for example, then I am currently getting employees missed off the list
For document 2 I would want to see
EID Signature
1 Bob
2
3 Fred
For document 4 I would want to see:
EID Signature
1
2
3
and for document 1:
EID Signature
1 Bob
2 Tom
3
The query I have tried to use is:
SELECT e.eid, s.signature
from employees e
left join signatures s on e.eid=s.eid
where s.document=? or s.document IS NULL group by e.eid
There are multiple issues:
Whenever using Left Join, any Where conditions on the right-side tables, should be put in the On clause. Otherwise, it will filter your result-set, even if there is no matching row (losing the purpose of Left Join)/
To compare null values, we use IS NULL. = null does not work. In this case, if we shift the conditions to On clause, we don't need to check for null values either.
Group By usage is invalid and really not required. When using Group By, only aggregated columns or the columns specified in Group By should come in Select. Refer: https://stackoverflow.com/a/41887524/2469308
Try the following:
SELECT e.eid, s.signature
FROM employees e
LEFT JOIN signatures s
ON e.eid=s.eid AND
s.document = ?
ID NAME Email
1 John john#example.com
2 Mathew mathew#example.com
3 John jon#example.com
4 Johnson johns#example.com
5 Peter pete#example.com
How can I create a query that will return
1 John john#example.com
3 John jon#example.com
4 Johnson johns#example.com
Ansers like that for Find rows that have the same value on a column in MySQL returns rows with same value. Here I need similar values
Get all the records with similar email first and then only print those records that match the inner condition.
select * from table_name where email in (
select email from table_name
group by email
having count(*)>1
)
Tested and working fine.
Here is my tables
|users|
|id| |lastname1| |lastname2| |name| |company_name|
1 Messi Ramirez Lionel
2 Gates Bush Bill
3 Klose Kazer Miroslav
4 Ozil Demon Mezut
5 Facebook
6 GMAIL
7 MYSPACE
8 Twitter
I'm trying to order company_name like a lastname1.
Some friends gave me this code but is not working with blank values just with NULL values:
select * from users
order by COALESCE(lastname1,company_name),lastname2,name ASC;
I should have this answer
Note: the first letter of "facebook" is F and "Gates" is G so it continues with the next letter.
5 Facebook
2 Gates Bush Bill
6 GMAIL
3 Klose Kazer Miroslav
1 Messi Ramirez Lionel
7 MYSPACE
4 Ozil Demon Mezut
8 Twitter
Please somebody can help me?
Use coalesce():
order by coalesce(lastname1, company_name)
I'm not sure what the other columns are contributing to the order by so I removed them.
EDIT:
If the values are blank or spaces and not NULL, then use case:
order by (case when trim(lastname1) = '' or lastname1 is null then company_name
else lastname1
end)
You could do this with this query:
select * from users
order by COALESCE(lastname1,company_name),lastname2,name ASC;
COALESCE takes the first non null element of it's list.
DEMO
If as in the modified question empty strings should be considered equally to NULL then you could do this with
select * from users
order by
CASE
WHEN TRIM(lastname1) = '' THEN company_name
WHEN lastname1 IS NULL THEN company_name
ELSE lastname1
END;
Demo