How can I avoid duplicate usernames while joining 2 tables - mysql

I have two tables related to user information:
Table 1(Users) contains columns like id,username and email
Table 2(details) contains columns like user_id,degree_name and degree
when I am joining these two tables, result I am getting is:
name degree_name degree
john doe Metric Science
john doe Fsc Engineering
john doe Bsc BSCS
herald Metric Science
Matt Metric Science
In above records "john doe" is repeating 3 times. what should be not expected result.
The result I want here is and also I know can be achievable by using find_in_set() is:
0: {name: john doe
details: {0: {degree: "Science",degree_name: "Metric"}
1: {degree: "Fsc",degree_name: "Engineering "}
2: {degree: "Science",degree_name: "BSCS"}}}
1: {name: herald
details: {0: {degree: "Science",degree_name: "Metric"}}}
2: {name: Matt
details: {0: {degree: "Science",degree_name: "Metric"}}}
Is there anybody who guide me for the right query?

You can use group_concat for degree and degree_name. eg . :
SELECT name, group_concat(degree), group_concat(degree_name) FROM Table1,Table2 WHERE Table1.id=Table.User_id. GROUP BY Table1.id
It will give you result with one row for one user.
Jon Doe | Metric,Fsc,Bsc | Science,Eng,BCSc.

SELECT u.username, CONCAT('{ "array": [',
GROUP_CONCAT(CONCAT('{"degree_name": "',
d.degree_name,
'", "degree": "',
d.degree,
'"}'
) separator ','),
']}') As details
FROM details d
INNER JOIN users u
ON FIND_IN_SET(u.id, d.user_id) > 0
GROUP BY u.id;
This query will provide the answer as expected. Just need a little over head to json parse records after getting results.

Related

MySQL substring_index Delete Everything In Field After Space

I have a table called subscribers with a name field that contains data like this:
Tom Jones
Drew Brees
Tom Brady III
I need to delete everything after the first space for each record so that it looks like:
Tom
Drew
Tom
Using this question, I assembled the following query:
select substring_index(name,' ',1) as deleteAllAfterSpace from subscribers
I get the following error:
Current selection does not contain a unique column.
When I run:
SELECT * FROM subscribers WHERE INSTR(name, ' ') > 0
I do get the values I'm looking for as described.
I can assure you, name column is unique? What am I doing wrong?
SELECT name, subString(name, 1, POSITION(' ' IN name)) as deleteAllAfterSpace
FROM subscribers;
Here is all you n

SQL query to get number of times a field repeats for another specific field

Let's say I have two fields in a table. For the purpose of discussion let's say the fields are first name and last name. I want to know how many times the first name shows up listed next to the same last name. Assuming the last name column is unique, how do I figure out how many times each first name exists for each last name?
i.e. let's say I have a table with the following data:
Smith, John
Smith, David
Smith, Jane
Smith, John
Smith, John
Black, John
Black, Jane
Black, Jack
Black, Samantha
Black, Jack
I want a result that tells me that for Smith, there are 3 Johns, 1 David and 1 Jane, and for Black, there are 2 Jacks, 1 Jane and 1 Samantha.
Not sure how to format the output best. Maybe simply:
Smith, John, 3, David, 1, Jane, 1
Black, Jack, 2, Jane, 1, Samantha, 1
Something that would allow me to easily output something like:
Smith: John (3), David (1), Jane (1)
Black: Jack (2), Jane (1), Samantha (1)
It's important to note that it's possible that the second field can repeat, so counting unique instances in the column is not useful. It's only useful in reference to the first field.
Thanks.
You can use a correlated sub-query in your SELECT statement and then wrap it all in a concat function to get the inline result you wanted
SELECT DISTINCT
CONCAT(LastName, ': ', FirstName, '(', (SELECT COUNT(FirstName) FROM Person WHERE FirstName = p.FirstName AND LastName = p.LastName),')')
FROM Person p
Simple aggregation?
select last_name, first_name, count(*)
from myTable
group by last_name, first_name
order by last_name, first_name
Displaying it in a Smith, John, 3, David, 1, Jane, 1 format will probably fail because there are way too many Smiths with way too many different last names.
My solution:
select name,surname, count(surname) over (partition by name) as cnt
from your_table
You can use this.
SELECT CONCAT( Name,':', GROUP_CONCAT(CONCAT( LastName, ' (', CNT , ')' ), ' ') )
FROM (
SELECT Name, LastName, COUNT(*) CNT FROM MyTable
GROUP BY
Name, LastName
) T
GROUP BY Name
Sql Fiddle
Result:
Black:Jane (1) ,John (1) ,Samantha (1) ,Jack (2)
Smith:David (1) ,Jane (1) ,John (3)

MYSQL, is this kind of request possible?

I have persons (table person) who have 0 or N roles (tables role and personne_role).
I want to select all the persons , with the roles they have, to have this kind of result :
PHIL COLLINS | Drummer | Singer
MIKE RUTHERFORD | Singer
ION ANDERSON | Singer
MIKE JAGGER |
CARLOS SANTANA | Guitarist
......
Each line can have 0 or N roles.
To do that, I make 2 requests
the first one to get the employees (table person)
the second one to loop all the retrieved employees and retrieve each role of them (tables role and person_role)
It works BUT in the case of there are a lot of lines, it is not very efficient.
I would like the same result in 1 request.
Is it possible ?
What are the mysql keywords I must use to do that ?
Thanks for your feedback.
dominique
You could use a JOIN with a GROUP_CONCAT, something like:
SELECT person.name, role.roles
FROM person
LEFT JOIN (
SELECT person_id, GROUP_CONCAT(DISTINCT role SEPARATOR ' | ') roles
FROM person_role
GROUP BY person_id
) role ON (person.id = role.person_id)
EDIT: the fields name are just a guess, since you didn't show us the full table schema; also, if the roles are actually in a separate tale, say joined by a role_id, you'd need to add it to the subquery.

SQL Multiple queries of WHERE + AND from two columns

I have a database of orders that looks roughly like this
ORDER ID | AMOUNT | FIRSTNAME | LASTNAME
1 50 JOHN SMITH
2 60 PAUL JOHNSON
3 20 FRANK CAMERON
5 80 JOHN JOHNSON
I have a list of names that I need to pull their orders. For this example lets say "JOHN SMITH" and "PAUL JOHNSON"
I have tried a query like this
SELECT * FROM ORDERS WHERE FIRSTNAME IN ("JOHN", "PAUL") AND LASTNAME IN ("SMITH", "JOHNSON")
But obviously that didn't work how I wanted as it included. I'm not sure how to go about it but I need to search something like
WHERE FIRSTNAME,LASTNAME IN ("JOHN","SMITH";"PAUL","JOHNSON")
OR
WHERE (FIRSTNAME,LASTNAME) IN {("JOHN","SMITH")("PAUL","JOHNSON")}
Obviously I know little about SQL so I'm getting stuck on syntax and terminology of what to search for?
You can separate the logic with an OR like this:
SELECT * FROM ORDERS
WHERE
(FIRSTNAME = "JOHN" AND LASTNAME = "SMITH")
OR
(FIRSTNAME = "PAUL" AND LASTNAME = "JOHNSON")
You could do something like this
SELECT *
FROM ORDERS
WHERE concat(firstname, ' ', lastname) IN ('JOHN SMITH','PAUL JOHNSON')

MySQL GROUP_CONCAT and ORDER and merging columns help please

I've been pulling my hair out for two days trying to put a MySQL query together to pull some data together. This is beyond my level of experience with SQL, however.
The following query pulls the data that I need, but I need to format it differently so I can use it.
SELECT b.key, a.author, a.comment FROM action a, issue b
WHERE a.issueid=b.id AND a.actiontype='comment';
This produces output like so:
1 | joe | comment 3
3 | sally | comment 2
1 | sam | comment 2
2 | julie | comment 2
1 | bill | comment 1
3 | joe | comment 1
2 | sam | comment 1
b.key is unique and can contain 0-∞ a.comment. There is a 1-1 relationship with the a.author and a.comment and I must maintain the original association. The output seems to be in ascending order based on the date of a.comment.
I would like to do get the data into the following format (CSV,) merging the a.author and a.comment results into a single column:
"1", "bill - comment 1", "sam - comment 2", "joe - comment 1"
"2", "julie - comment 1", "sam - comment 2"
"3", "joe - comment 1", "sally - comment 2"
I played around with several combinations of GROUP_CONCAT and ORDER and also messed with subqueries a bit based on this post and can't seem to get it formatted the way I need. Additionally, it seems like the order of the comment column changes. I need to maintain the original (oldest to newest) order, but my original query above produces results in newest to oldest order. If the delimiters pose a problem, I can certainly do some post processing with perl or awk search & replace on the results. Any help is greatly appreciated!
How about
SELECT
issue.key,
GROUP_CONCAT(CONCAT(action.author, ' - ', action.comment) ORDER BY action.created ASC SEPARATOR '|')
FROM action
INNER JOIN issue
ON action.issueid = issue.id
WHERE action.actiontype = 'comment'
GROUP BY issue.key;
with some post processing to split based on the pipe character. If you get truncation issues you may need to increase the value of group_concat_max_len.
Check this out. The join doesn't affect in any way how data is displayed so I'm writing the query as if your table is actually the one you display as the output
select concat('"', id, '", ',
group_concat(concat('"', author, ' - ', comment, '"') separator ", ")
) as result from table1
group by id
The ordering of the group_concat is up to you.
Here is an example.
Hope this helps.