Combine two SQL tables with replacement? - mysql

Long story short, I need to be able to combine two tables (one is a continuation of the previous with a little overlap). I then need to set one column to be a Primary Key, which means no duplicates. When I tried to just use the Import Wizard in SQL Management Studio and import one table into the other, it just added all the data from one table into the next. I need to figure out some way or SQL command that will import all the data from the new table into the older table, and replace any existing duplicate data with the ones from the newer table.
Think of it like this, I have two tables with the following data:
People_Old table
+------+--------+
| Name | Color |
+------+--------+
| Mary | Blue |
| Katy | Yellow |
| Jim | Green |
| John | Red |
+------+--------+
People table
+------+--------+
| Name | Color |
+------+--------+
| Jim | Silver |
| John | Brown |
| Greg | Purple |
| Liz | Pink |
+------+--------+
Assuming the "Name" column are suppose to be a Primary Key, I would like to add the data from the newer "People" table into the older "People_Old" table, but replace the overlapping data so there are no duplicates. In this example, I would like the final "People_Old" table to be:
+------+--------+
| Name | Color |
+------+--------+
| Mary | Blue |
| Katy | Yellow |
| Jim | Silver |
| John | Brown |
| Greg | Purple |
| Liz | Pink |
+------+--------+

Use the REPLACE statement, something like:
replace into people_old select * from people;

DROP TABLE IF EXISTS old;
CREATE TABLE old
(Name VARCHAR(12) NOT NULL PRIMARY KEY
,Color VARCHAR(12) NOT NULL
);
INSERT INTO old VALUES
('Mary','Blue'),
('Katy','Yellow'),
('Jim','Green'),
('John','Red');
DROP TABLE IF EXISTS new;
CREATE TABLE new
(Name VARCHAR(12) NOT NULL PRIMARY KEY
,Color VARCHAR(12) NOT NULL
);
INSERT INTO new VALUES
('Jim' ,'Silver'),
('John','Brown'),
('Greg','Purple'),
('Liz' ,'Pink');
SELECT * FROM old;
+------+--------+
| Name | Color |
+------+--------+
| Mary | Blue |
| Katy | Yellow |
| Jim | Green |
| John | Red |
+------+--------+
SELECT * FROM new;
+------+--------+
| Name | Color |
+------+--------+
| Jim | Silver |
| John | Brown |
| Greg | Purple |
| Liz | Pink |
+------+--------+
INSERT INTO old
SELECT name
, color
FROM new
ON DUPLICATE KEY UPDATE old.color = new.color;
SELECT * FROM old;
+------+--------+
| Name | Color |
+------+--------+
| Mary | Blue |
| Katy | Yellow |
| Jim | Silver |
| John | Brown |
| Greg | Purple |
| Liz | Pink |
+------+--------+
6 rows in set (0.00 sec)

Related

MySQL Create entry for each row in a table

I know there must be an answer to this, but I can't seem to put the search terms together properly.
Say I have an existing table 'foo'
foo
| id | data1 | data2 | ... |
----------------------------
|1 | abc | def | ghi |
|2 | abc | def | ghi |
...
And I want to create a new table, bar that has a 1 to 1 relationship with foo where foo gets a new foreign key column called barId, and each entry of foo MUST have a related barID so the end result looks like:
foo
| id | data1 | data2 | ... | barID |
------------------------------------
|1 | abc | def | ghi | 1 |
|2 | abc | def | ghi | 2 |
...
bar
| id | dataA | dataB |
----------------------
| 1. | null | null |
| 2. | null | null |
The trouble I'm having is that after I define bar I am having trouble creating a row for each entry of foo, and subsequently setting foo.barId for each newly created bar record.
If I were to do this in a procedural language, I would write something like the pseudocode below
createTable(bar);
foo.createColumn("barId");
for each (entry in foo) {
barEntry = bar.createNewEntry();
entry.setBarId(barEntry.ID);
}
How can I accomplish this goal with MySQL?
What part(s) of the problem does the following fail to address?
DROP TABLE IF EXISTS users;
CREATE TABLE users
(user_id SERIAL PRIMARY KEY
,user_name VARCHAR(12) UNIQUE
);
DROP TABLE IF EXISTS user_role;
CREATE TABLE user_role
(user_id INT NOT NULL PRIMARY KEY
,role ENUM('guest','user','administrator')
);
INSERT INTO users VALUES (NULL,'John');
INSERT INTO user_role VALUES (LAST_INSERT_ID(),'administrator');
SELECT * FROM users;
+---------+-----------+
| user_id | user_name |
+---------+-----------+
| 1 | John |
+---------+-----------+
1 row in set (0.00 sec)
SELECT * FROM user_role;
+---------+---------------+
| user_id | role |
+---------+---------------+
| 1 | administrator |
+---------+---------------+
EDIT: And extending this idea, consider the following...
INSERT INTO users (user_name) VALUES ('Paul'),('George'),('Ringo');
INSERT IGNORE INTO user_role SELECT user_id, 'guest' FROM users;
SELECT * FROM users;
+---------+-----------+
| user_id | user_name |
+---------+-----------+
| 1 | John |
| 2 | Paul |
| 3 | George |
| 4 | Ringo |
+---------+-----------+
SELECT * FROM user_role;
+---------+---------------+
| user_id | role |
+---------+---------------+
| 1 | administrator |
| 2 | guest |
| 3 | guest |
| 4 | guest |
+---------+---------------+
Note that it's slightly unusual to store 1-1 relations in separate tables, but there can be valid reasons for doing so - particularly relating to permissions.

Get difference of unique and duplicate set - SQL

I have two similar data sets (table, view, CTE), one of which contains unique rows (guaranteed by DISTINCT or GROUP BY), the second contains duplicates (no primary key constraint involved).
How can I get the difference of two data sets so that I only get the duplicates of the second set in MySql 8?
Say I have a table called Animals, which stores NAME and SPECIES.
+---------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| ID | int(11) | NO | PRI | NULL | |
| NAME | varchar(255) | YES | | NULL | |
| SPECIES | varchar(255) | YES | | NULL | |
+---------+--------------+------+-----+---------+-------+
ANIMALS
+----+---------+-------------+
| ID | NAME | SPECIES |
+----+---------+-------------+
| 1 | Lion | Carnivorous |
| 2 | Giraffe | Herbivores |
| 3 | Zebra | Herbivores |
| 4 | Trutle | Herbivores |
| 5 | Tiger | Carnivorous |
| 6 | Bear | Carnivorous |
+----+---------+-------------+
With that in place, I define the view DUPLICATED.
CREATE VIEW DUPLICATED AS
SELECT * FROM ANIMALS
UNION ALL
SELECT * FROM ANIMALS WHERE SPECIES = "Carnivorous";
(Duplicates every Carnivorous in the set)
DUPLICATED
+---------+-------------+-----+
| NAME | SPECIES | CNT |
+---------+-------------+-----+
| Lion | Carnivorous | 2 |
| Tiger | Carnivorous | 2 |
| Bear | Carnivorous | 2 |
| Giraffe | Herbivores | 1 |
| Zebra | Herbivores | 1 |
| Trutle | Herbivores | 1 |
+---------+-------------+-----+
Now I want to get the difference of SELECT * FROM ANIMALS and DUPLICATED or vice versa, essential getting all Carnivorous from ANIMALS.
Basically you can group by whatever combination of fields that guarantee the uniqueness of a record in your result. you haven't provided your queries or your table's schema, so i will try to demonstrate this using a general example. you can get my drift and apply it to your query.
SELECT field1, field2, field3 COUNT(*)
FROM MyTable
GROUP BY field1, field2, field3
HAVING COUNT(*) > 1

Open a record, update it and insert as new record in MySQL

I have a db with 10 fields, of which only a few change very often. I would like to open the current record, update it, and enter it back into the db with a new auto id while retaining the previous record.
If I INSERT a new record, I have to re-enter all the info even tho it may not have changed.
If I UPDATE a record, it overwrites the previous values.
Any suggestion would be greatly appreciated
How about a suitably modified version of
insert into table select * from table where id='current_id'
Sample query:Say i want to read first record ,lift student, subject but change marks and insert a new record
insert into score(student,subject,marks)
select student,subject,'30' from score where id=1;
Sample Data
+---------+---------+-------+----+
| student | subject | marks | id |
+---------+---------+-------+----+
| A1 | phy | 20 | 1 |
| A1 | bio | 87 | 2 |
| A2 | che | 24 | 3 |
| A3 | che | 50 | 4 |
Table structure:
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| student | varchar(20) | YES | | NULL | |
| subject | varchar(20) | YES | | NULL | |
| marks | int(1) | YES | | NULL | |
| id | int(10) | NO | PRI | NULL | auto_increment |
+---------+-------------+------+-----+---------+----------------+
You can do it via two different queries: SELECT and INSERT, or you can use INSERT INTO SELECT construction. Check documentation for complete reference http://dev.mysql.com/doc/refman/5.0/en/insert-select.html

MySQL tables are not aligned right

I have a question which relates to MySQL. The problem can be seen in these two images:
http://imgur.com/NrOwSxS,yPo9Cra
http://imgur.com/NrOwSxS,yPo9Cra#1
Does anyone know why MySQL is doing this? It should show up as a nice and neat table, not this bundle of gibberish. Thanks in advance! :D
First, to show that there's nothing really wrong, try this query:
SELECT firstname FROM contact_info
That should look good. Now try this:
SELECT firstname, lastname FROM contact_info
That's how you pick individual columns.
Really you want to capture output to a file, this page shows you how: The MySQL Command-Line Tool
Then you can learn to use other programs to format it nicely.
I assume you created your table somewhat like this:
create table automobile (make char(10),model char(10),year int, color char(10), style char(50), MSRP int);
insert into automobile values ('Ford','Mustang',2006,'Blue','Convertible',27000);
insert into automobile values ('Toyota','Prius',2005,'Silver','Hybrid',22000);
insert into automobile values ('Toyota','Camry',2006,'Blue','Sedan',26000);
insert into automobile values ('Dodge','1500',2005,'Green','Pickup',26000);
so a
describe automobile
will show you your columns as:
+-------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| make | char(10) | YES | | NULL | |
| model | char(10) | YES | | NULL | |
| year | int(11) | YES | | NULL | |
| color | char(10) | YES | | NULL | |
| style | char(50) | YES | | NULL | |
| MSRP | int(11) | YES | | NULL | |
+-------+----------+------+-----+---------+-------+
as long as your columns in total are smaller than your terminal's width you should see
the expected result:
mysql> select * from automobile;
+--------+---------+------+--------+-------------+-------+
| make | model | year | color | style | MSRP |
+--------+---------+------+--------+-------------+-------+
| Ford | Mustang | 2006 | Blue | Convertible | 27000 |
| Toyota | Prius | 2005 | Silver | Hybrid | 22000 |
| Toyota | Camry | 2006 | Blue | Sedan | 26000 |
| Dodge | 1500 | 2005 | Green | Pickup | 28000 |
+--------+---------+------+--------+-------------+-------+
if you'd like the result smaller then pick the columns you'd like to see e.g.
select make,model from automobile
mysql> select make,model from automobile;
+--------+---------+
| make | model |
+--------+---------+
| Ford | Mustang |
| Toyota | Prius |
| Toyota | Camry |
| Dodge | 1500 |
+--------+---------+
to make the content of a column smaller you may use the left string function
select left(make,4) as make, left(model,5) as model,left(style,5) as style from automobile;
+------+-------+-------+
| make | model | style |
+------+-------+-------+
| Ford | Musta | Conve |
| Toyo | Prius | Hybri |
| Toyo | Camry | Sedan |
| Dodg | 1500 | Picku |
+------+-------+-------+
You can try supplying a line separator character in the end.
mysql> LOAD DATA LOCAL INFILE *file_path* INTO *table_name* LINES TERMINATED BY '\r\n';
Separator character may vary for editors. In Windows, most editors use '\r\n'.

how to get all enum field in a column side by side seperated by comma (,) in a mysql by query

In mysql i need to get enum fields side by side in a column when i run a query with group by , just like as follows.
There is table as like below
mysql> describe tabex;
+---------+----------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+----------------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| personid| int(11) | YES | | NULL | |
| color | enum('red','blue','white') | YES | | NULL | |
+---------+----------------------------+------+-----+---------+----------------+
there are different shirts , the column personid describes the that person id and color indicates the color of his shirt..
the data in table is as follows
mysql> select * from tabex;
+----+----------+-------+
| id | personid | color |
+----+----------+-------+
| 1 | 1 | red |
| 2 | 1 | white |
| 3 | 2 | blue |
| 4 | 2 | red |
+----+----------+-------+
4 rows in set (0.00 sec)
when i ran a query i am getting results like this
mysql> select personid , color from tabex group by personid;
+----------+-------+
| personid | color |
+----------+-------+
| 1 | red |
| 2 | blue |
+----------+-------+
but i want the result like below
+----------+-------------+
|personid | color |
+----------+-------------+
|1 | red,white |
|2 | blue,red |
| | |
+----------+-------------+
how can i get the result as above by using group by and aggregation (if any for enum).
that is here i want to get the result for enum fields as like we will get by using count or sum functions and group by .
The GROUP_CONCAT() aggregate function does what you want:
SELECT personid, GROUP_CONCAT(color) colors
FROM tabex
GROUP BY personid
This works with any kind of field, not just ENUM.