How to merge multiple rows in MySQL? - mysql

I ran into some problems while structuring my database, and I will ask two questions.
First question: below table needs to be merged by the same IDs
╔═════╦═══════╦═════╦═══════╗
║ id* ║ name ║ age ║ grade ║
╠═════╬═══════╬═════╬═══════╣
║ 0 ║ John ║ ║ ║
║ 0 ║ ║ 11 ║ ║
║ 0 ║ ║ ║ 6 ║
║ 1 ║ Dave ║ ║ ║
║ 1 ║ ║ 12 ║ ║
║ 1 ║ ║ ║ 7 ║
╚═════╩═══════╩═════╩═══════╝
so it should look like this;
╔═════╦═══════╦═════╦═══════╗
║ id* ║ name ║ age ║ grade ║
╠═════╬═══════╬═════╬═══════╣
║ 0 ║ John ║ 11 ║ 6 ║
║ 0 ║ Dave ║ 12 ║ 7 ║
╚═════╩═══════╩═════╩═══════╝
NOTE: id* is not AUTO_INCREMENT
Second question: You probably think that the former database structure is poor. The good thing is, I haven't created the database yet and I have been looking for a solution to add data to an existing row without removing old information, but if there is no old information, it would create a new row. Thanks in advance.
Second question explained
Virgin table
╔═════╦═══════╦═════╦═══════╗
║ id* ║ name ║ age ║ grade ║
╠═════╬═══════╬═════╬═══════╣
║ ║ ║ ║ ║
╚═════╩═══════╩═════╩═══════╝
some SQL statement
╔═════╦═══════╦═════╦═══════╗
║ id* ║ name ║ age ║ grade ║
╠═════╬═══════╬═════╬═══════╣
║ 0 ║ John ║ ║ ║
╚═════╩═══════╩═════╩═══════╝
the same SQL statement with different parameters
╔═════╦═══════╦═════╦═══════╗
║ id* ║ name ║ age ║ grade ║
╠═════╬═══════╬═════╬═══════╣
║ 0 ║ John ║ ║ ║
║ 1 ║ Dave ║ ║ ║
╚═════╩═══════╩═════╩═══════╝
another SQL statement
╔═════╦═══════╦═════╦═══════╗
║ id* ║ name ║ age ║ grade ║
╠═════╬═══════╬═════╬═══════╣
║ 0 ║ John ║ ║ ║
║ 1 ║ Dave ║ 12 ║ ║
╚═════╩═══════╩═════╩═══════╝
another SQL statement
╔═════╦═══════╦═════╦═══════╗
║ id* ║ name ║ age ║ grade ║
╠═════╬═══════╬═════╬═══════╣
║ 0 ║ John ║ ║ 6 ║
║ 1 ║ Dave ║ 12 ║ ║
╚═════╩═══════╩═════╩═══════╝
... and so on.

You should be able to apply an aggregate function to all the columns and then GROUP BY id:
select id,
max(name) name,
max(age) age,
max(grade) grade
from yourtable
group by id
See SQL Fiddle with Demo
As far as the DB structure, the only issue that I see is that you are inserting multiple records for the same user. You should be using an UPDATE statement to use the values instead of inserting.
It sounds like you want to use the REPLACE function in MySQL (here is a tutorial).
So the query would be similar to this:
REPLACE
INTO yourtable (`id`, `name`, `age`, `grade`)
VALUES (0, 'john', 11, null);
See SQL Fiddle with Demo

You could group by id, and use any aggregate function to pick the non-null row. This example uses max, but min would work too:
select id
, max(name) as name
, max(age) as age
, max(grade) as grade
from YourTable
group by
id

Related

using condition for Group_Concat

I want to find all ids of which group_concat only contains 'a'.
Here is simplified table from mine.
╔════╦══════════════╦
║ id ║ group_concat ║
╠════╬══════════════╬
║ 1 ║ a,b,b ║
║ 2 ║ a ║
║ 3 ║ a,a ║
║ 4 ║ a,a,a ║
║ 5 ║ a,b,a ║
╚════╩══════════════╩
And the table below is what I want to achieve.
╔════╦══════════════╦
║ id ║ group_concat ║
╠════╬══════════════╬
║ 2 ║ a ║
║ 3 ║ a,a ║
║ 4 ║ a,a,a ║
╚════╩══════════════╩
And this is the query statement I am trying to use.
select id, group_concat(val)
from user
group by id
having group_concat(val) = 'a'
Thanks in advance
Try this:
select id, group_concat(val)
from user
group by id
having count(distinct val) = 1 and max(val) = 'a'

Efficient use of Sum in query within the same id

I am learning sql query.
Here is my table simplified
╔════╦══════════════╦══════════════╦════════╦
║ id ║ user_id ║ department_id║ salary ║
╠════╬══════════════╬══════════════╬════════╬
║ 1 ║ 1 ║ 3 ║ 100 ║
║ 2 ║ 2 ║ 3 ║ 50 ║
║ 3 ║ 1 ║ 3 ║ 30 ║
║ 4 ║ 2 ║ 3 ║ 20 ║
║ 5 ║ 2 ║ 3 ║ 20 ║
╚════╩══════════════╩══════════════╩════════╩
Here is what I want to have below
╦══════════════╦══════════════╦════════╦
║ user_id ║ department_id║ salary ║
╠══════════════╬══════════════╬════════╬
║ 1 ║ 3 ║ 130 ║
║ 2 ║ 3 ║ 90 ║
╚══════════════╩══════════════╩════════╩
I want to add user salary if they are in the same department.
I have nooo ideas how to start.
Does anyone have good feedback that I can start with?
Thank you in advance
Try this query:
Select user_id, department_id, sum(salary) from table
Group by user_id, department_id
In the select clause, you have the columns you wish to select and your group by clause contains the grouping.

Access 2007 - Price Code from a Price Table

I have two tables. members and codes
I'm trying to get members.price to be automatically filled each time a new record is inserted - based on the code in members.price_code. It should match the codes.code and insert the correct codes.price in to members.price
I also need to do this for any existing members that currently have their codes set correctly, but the price field is empty
My members table:
╔════╦══════════════╦═════════════╦═══════╗
║ id ║ name ║ price_code ║ price ║
╠════╬══════════════╬═════════════╣═══════║
║ 1 ║ John Doe ║ M ║ ? ║
║ 2 ║ Jane Doe ║ M ║ ? ║
║ 3 ║ Peter Doe ║ S ║ ? ║
║ 4 ║ Lisa Doe ║ M ║ ? ║
╚════╩══════════════╩═════════════╩═══════╝
My Codes table
╔══════╦═══════════════╦═══════╗
║ code ║ description ║ price ║
╠══════╬═══════════════╬═══════╣
║ M ║ Member ║ 100 ║
║ S ║ Student ║ 50 ║
╚══════╩═══════════════╩═══════╝

how to create dynamic pivot tables in MySQL

I'm having trouble generating pivot tables in MySQL and wonder if anyone can give me any tips and some documentation so I can finally resolve this problem.
My problem is as follows:
I have 2 tables in my database. clients contains customer information such as name, ssn and some personal data. In the cli_location table are client locations: address, telephone number, mobile phone and so on.
Sometimes we need to do selects based on criteria such as location, to pick up customers in a particular city. We also make queries based on cpf to get information for a specific customer.
I often need to cross these two tables. I currently do a left join. The problem with the left join is that sometimes the client has more than one phone, which generates new lines for each one.
When researching how to improve this behavior I discovered pivot tables, however I am not able to understand them.
1st table (clients):
╔════╦══════╦═══════╦════════════╦═══════╦════════╗
║ id ║ name ║ ssn ║ dt_birth ║ store ║ value ║
╠════╬══════╬═══════╬════════════╬═══════╬════════╣
║ 1 ║ john ║ 12345 ║ 1991-11-04 ║ 318 ║ 34.33 ║
║ 2 ║ john ║ 12345 ║ 1991-11-04 ║ 318 ║ 654.44 ║
║ 3 ║ john ║ 12345 ║ 1991-11-04 ║ 212 ║ 238.00 ║
║ 4 ║ alex ║ 54321 ║ 1988-05-20 ║ 321 ║ 334.44 ║
╚════╩══════╩═══════╩════════════╩═══════╩════════╝
2st table(cli_location):
╔════╦══════╦═══════╦══════════╦════════╦═════════╦═══════╦══════════╗
║ id ║ name ║ ssn ║ address ║ city ║ state ║ zip ║ tel ║
╠════╬══════╬═══════╬══════════╬════════╬═════════╬═══════╬══════════╣
║ 1 ║ john ║ 12345 ║ street1 ║ city1 ║ state1 ║ 23443 ║ 23432122 ║
║ 2 ║ john ║ 12345 ║ street1 ║ city1 ║ state1 ║ 23443 ║ 98765434 ║
║ 3 ║ john ║ 12345 ║ street2 ║ city5 ║ state7 ║ 54323 ║ 65765567 ║
║ 4 ║ john ║ 12345 ║ street3 ║ city4 ║ state9 ║ 76543 ║ 44323455 ║
║ 5 ║ alex ║ 54321 ║ street34 ║ city30 ║ state33 ║ 43234 ║ 86643457 ║
╚════╩══════╩═══════╩══════════╩════════╩═════════╩═══════╩══════════╝
When crossing the tables using left join, with the field of reference being ssn, the result has many duplicate lines. I am not able to change the structure of the data in production.
I had thought about doing something like :
╔════╦══════╦═══════╦════════════╦═══════╦════════╦════════╦════════╦════════╦════════╦══════════╦════════╦═════════╦═══════╦══════════╦════════╦════════╦════════╦══════════╦════════╦════════╦════════╦══════════╦══════════╦══════════╦══════════╗
║ id ║ name ║ ssn ║ dt_birth ║ store ║ value ║ store1 ║ value1 ║ store2 ║ value2 ║ address ║ city ║ state ║ zip ║ address1 ║ city1 ║ state1 ║ zip1 ║ address2 ║ city2 ║ state2 ║ zip2 ║ tel ║ tel1 ║ tel2 ║ tel3 ║
╠════╬══════╬═══════╬════════════╬═══════╬════════╬════════╬════════╬════════╬════════╬══════════╬════════╬═════════╬═══════╬══════════╬════════╬════════╬════════╬══════════╬════════╬════════╬════════╬══════════╬══════════╬══════════╬══════════╣
║ 1 ║ john ║ 12345 ║ 1991-11-04 ║ 318 ║ 34.33 ║ 318 ║ 654.44 ║ 212 ║ 238.00 ║ street1 ║ city1 ║ state1 ║ 23443 ║ street2 ║ city5 ║ state7 ║ 54323 ║ street3 ║ city4 ║ state9 ║ 76543 ║ 23432122 ║ 98765434 ║ 65765567 ║ 44323455 ║
║ 4 ║ alex ║ 54321 ║ 1988-05-20 ║ 321 ║ 334.33 ║ (null) ║ (null) ║ (null) ║ (null) ║ street34 ║ city30 ║ state33 ║ 43234 ║ (null) ║ (null) ║ (null) ║ (null) ║ (null) ║ (null) ║ (null) ║ (null) ║ (null) ║ 86643457 ║ (null) ║ (null) ║
╚════╩══════╩═══════╩════════════╩═══════╩════════╩════════╩════════╩════════╩════════╩══════════╩════════╩═════════╩═══════╩══════════╩════════╩════════╩════════╩══════════╩════════╩════════╩════════╩══════════╩══════════╩══════════╩══════════╝
The idea is to generate columns dynamically as there are more lines with the same type of information, as in the above table. Even if there are 2 rows with the same store, the value of field value differs so columns must be added for each store-value pair. The same for the address and phone fields as in the table above.
If someone could point me to some documentation, show me any examples or anything that helps me learn how to do this kind of thing I would be very grateful!
Edit
Thinking about this further, I'm confident that SQL can not do exactly what you need. This answer explains why, and lists your choices:
write application code to build a query dynamically, or
run your existing left join query, and then write application code to manipulate the result into the desired format.
However, if you're comfortable combining multiple values into one column, group_concat might get you close:
select
ssn,
name,
group_concat(distinct tel separator ', ') phones,
group_concat(distinct address separator '; ') addresses
from
(select clients.ssn,
clients.name,
cli_location.tel,
concat(cli_location.address, ', ', city, ' ', zip) address
from clients
left join cli_location
on clients.ssn=cli_location.ssn) c
group by ssn
produces:
| SSN | NAME | PHONES | ADDRESSES |
|-------|------|----------------------------------------|------------------------------------------------------------------|
| 12345 | john | 23432122, 44323455, 65765567, 98765434 | street1, city1 23443; street3, city4 76543; street2, city5 54323 |
| 54321 | alex | 86643457 | street34, city30 43234 |
http://sqlfiddle.com/#!2/ca287/25
Original
If you want a list of customers in a particular city:
select clients.ssn, clients.name
from clients
inner join cli_location
using(ssn)
where city = 'city1'
group by ssn;
http://sqlfiddle.com/#!2/ca287/3
Your schema is making this more difficult than it should be though. Consider normalizing it so that client names are in only one table, and split one-to-many relationships (like client:phone) into separate tables.

summing records

I have one table of records like
╔═════╦══════╦══════════╦══════════╗
║ PID ║ NAME ║ DATE1 ║ DATE2 ║
╠═════╬══════╬══════════╬══════════╣
║ 123 ║ john ║ 20110401 ║ 19700101 ║
║ 123 ║ john ║ 20110401 ║ 19700101 ║
║ 123 ║ john ║ 20110401 ║ 19700101 ║
║ 323 ║ mike ║ 20110401 ║ 19900101 ║
║ 323 ║ mike ║ 20110401 ║ 19900101 ║
╚═════╩══════╩══════════╩══════════╝
query1 is count on pid
query2 is if all the four fields are same the record is to be taken as one record else individual records and records to be counted on pid order.
The above result is:
╔═════╦══════════════╦═════════════╗
║ PID ║ TOTALRECORDS ║ TOTALUNIQUE ║
╠═════╬══════════════╬═════════════╣
║ 123 ║ 3 ║ 1 ║
║ 323 ║ 2 ║ 1 ║
╚═════╩══════════════╩═════════════╝
I did select pid,count(pid),(select count(pid) group by pid,name,date1,date2) from <table> group by pid;
But I get an error... kindly correct my code.
SELECT pid,
COUNT(*) totalRecords,
COUNT(DISTINCT name, date1, date2) totalUnique
FROM TableName
GROUP BY pid
SQLFiddle Demo
SQLFiddle Demo (with not unique record)
Result
╔═════╦══════════════╦═════════════╗
║ PID ║ TOTALRECORDS ║ TOTALUNIQUE ║
╠═════╬══════════════╬═════════════╣
║ 123 ║ 3 ║ 1 ║
║ 323 ║ 2 ║ 1 ║
╚═════╩══════════════╩═════════════╝