I would like to vertically split an existing (already filled with data).
Say my starting table (trip) looks like this:
ID Person Age Trip_to Date
... Alice 21 Los Angeles 2015-04-01
... Bob 35 New York 2015-03-15
... Bob 35 Chicago 2015-03-20
... Bob 35 San Francisco 2015-03-29
... Carol 29 Miami 2015-03-30
... Carol 29 Boston 2015-04-05
I would like to split this table into two tables, as it should be, one each for person and trip.
When copying each unique person into a table person, I want the automatically created uniqueidentifier column in that table person.pId (the primary key) to be copied into a newly created uniqueidentifier column trip.personid in the original table and turn that into a foreign key. (I would then delete the trip.person and trip.age column from the original table, and have the data structured as I want them.)
I thought I could use a trigger for that when I insert the person rows into the new table, like so:
CREATE TRIGGER tr_person
on person
after INSERT
as
begin
UPDATE Trip
SET personId=(SELECT i.pId from inserted i)
WHERE person=(SELECT i.person from inserted i) and age=(SELECT i.age from inserted i)
END
However, I get this:
Subquery returned more than 1 value.
This is not permitted when the subquery follows =, !=, <, <= , >, >=
or when the subquery is used as an expression.
Apparently the trigger only executes after all (potentially multiple!) inserts have been carried out, and by that time a query on inserted is no longer allowed for my SET statement.
I also thought about using an OUTPUT clause on the INSERT statement, but that wouldn't work either
Insert into person (Driver, Age)
OUTPUT inserted.pId INTO trip.personId WHERE trip.person=inserted.person AND trip.Age=inserted.Age
(Select DISTINCT Person, Age FROM Trip)
So I am wondering now, am going about this all wrong? Is there another way to automagically create the keys and relationships between the two newly split tables?
EDIT Desired result:
Table trip:
ID Trip_to Date PersonId
... Los Angeles 2015-04-01 xxxx1
... New York 2015-03-15 xxxx2
... Chicago 2015-03-20 xxxx2
... San Francisco 2015-03-29 xxxx2
... Miami 2015-03-30 xxxx3
... Boston 2015-04-05 xxxx3
Table person
pId Person Age
xxxx1 Alice 21
xxxx2 Bob 35
xxxx3 Carol 29
(The ID fields should all be uniqueidentifiers, of course)
Here is an idea:
First, you insert all distinct Person from Trip table to Person table:
CREATE TABLE Person(
pID UNIQUEIDENTIFIER PRIMARY KEY,
Person VARCHAR(10),
Age INT
)
INSERT INTO Person
SELECT
NEWID(), Person, Age
FROM(
SELECT DISTINCT Person, Age FROM Trip
)t
Then, add a new FK column to Trip table PersonId which references pId from the Person table:
ALTER TABLE Trip
ADD PersonId UNIQUEIDENTIFIER
FOREIGN KEY(PersonId) REFERENCES Person(pId)
Then, UPDATE the newly added FK column with values from Person table using a JOIN on Person and Age:
UPDATE t
SET PersonId = p.pID
FROM Trip t
INNER JOIN Person p
ON p.Person = t.Person
AND p.Age = t.Age
Finally, you can drop Person and Age from Trip table:
ALTER TABLE Trip DROP COLUMN Person
ALTER TABLE Trip DROP COLUMN Age
RESULT
Person
pID Person Age
------------------------------------ ---------- -----------
35815766-1634-45FF-A3F6-8194B43F3F65 Alice 21
8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67 Bob 35
D0EDCEA8-3825-4693-9352-BF7A04AEFCB2 Carol 29
Trip
ID Trip_to Date PersonId
------------------------------------ -------------------- ---------- ------------------------------------
77357A57-FAAE-43DE-923E-219038B8641E Los Angeles 2015-04-01 35815766-1634-45FF-A3F6-8194B43F3F65
C1B64E81-D30A-46A9-A868-1D92C4B64B8C New York 2015-03-15 8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67
21F3614A-8E76-4A64-8A0B-815D5343FC26 Chicago 2015-03-20 8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67
E1DB1926-4268-4BFA-B5E0-DA603DA8E1B7 San Francisco 2015-03-29 8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67
F50E45E6-E689-444B-96C1-F936CA6F3D2A Miami 2015-03-30 D0EDCEA8-3825-4693-9352-BF7A04AEFCB2
C2FA7073-79D7-42E8-B2C8-6EEDBC374002 Boston 2015-04-05 D0EDCEA8-3825-4693-9352-BF7A04AEFCB2
Side note: You should not be storing the Age of the person. Instead, store the birthdate and compute the age on the fly.
Related
I have a table like the following:
Table 1: Person_Favorite_Food
id name address favorite_food
------------------------------------------
1 Dave 123 Cherry Ln Pizza
2 Dave 123 Cherry Ln Cheeseburger
3 Dave 456 Peachtree St Ice cream
4 Cindy 789 Grove Rd Pizza
id - primary key
unique key constraint on the following columns: name, address and food
Since each person can have more than one favorite food item I'd like to split Table 1 into two tables like the following:
Table 2: Person
id name address
--------------------------
1 Dave 123 Cherry Ln
3 Dave 456 Peachtree St
4 Cindy 789 Grove Rd
Table 3: Person_Favorite_Food
person_id favorite_food
-----------------
1 Pizza
1 Cheeseburger
3 Ice cream
4 Pizza
How would I go about doing this in Oracle?
Note: In the original table Rows 1 and 2 represent favorite food for the same person so the favorite food entries in the Person_Favorite_Food table will need to have the same identifier for both of those entries although the identifiers are different in the initial table.
You can use:
create table new1 as
select distinct id, name, address
from t;
create table new2 as
select id, favorite_food
from t;
I would recommend create two new tables and not trying to morph the existing table into one of the new ones.
Use simple aggregation to create table person:
create table person as
select min(id) id, name, address
from person_favorite_food
group by name, address;
Use the same query in merge to change id for some rows:
merge into person_favorite_food a
using (select min(id) id, name, address from person_favorite_food group by name, address) b
on (a.name = b.name and a.address = b.address)
when matched then update set a.id = b.id;
Drop unwanted columns:
alter table person_favorite_food drop (name, address);
Done. Demo in dbfiddle.
I'm seriously struggling with some easy stuff.
Currently I have 2 tables (tmp_jmo and persons)
table tmp_jmo
----------
ID ADRESS PERSON_ID
115 Street 1 (null)
120 Street 2 (null)
121 Street 3 (null)
Table persons
ID NAME PERSON_ID
----------
115 John 14
120 Ellen 27
121 Mark 114
Now I want to update the Peson_id from tmp_jmo with the values from person_id (persons table)
In this case I've getting the error that there are to many values
Update tmp_jmo t SET person_id = persons.person_id where tmp_jmo.id = persons.id;
I've also tried to with temporary data but also failing.
I'm sorry to interrupt you with this kind of questions but it's ruining my day!
Many thanks!
In Standard SQL, you can do:
update tmp_jmo t
set person_id = (select p.person_id from persons p where tmp_jmo.id = p.id);
Many databases also support join or from in updates, but that is database-specific syntax.
This is my source table
Book | Employee | StartDate | EndDate
-------------------------------------
ABC PQR 02/02/2014 06/06/2014
QWE MNO 03/03/2014 07/07/2014
This is the DB schema, where this data should fit in...
Book table
BookID | BookName
-----------------
1 ABC
2 QWE
Employee table
EmployeeID | EmployeeName
-------------------------
1 PQR
2 MNO
BookEmployee table
BookID | EmployeeID | StartDate | EndDate
------------------------------------------
1 1 02/02/2014 06/06/2014
2 2 03/03/2014 07/07/2014
Note: if Book and Employee already exist in the Book and Employee tables, then we should not insert them, instead use their ID in the BookEmployee table
I would just do three queries.
INSERT INTO [Book] (BookName)
SELECT DISTINCT Book
FROM [Source]
WHERE Book NOT IN (SELECT BookName FROM Book)
INSERT INTO [Employee] (EmployeeName)
SELECT DISTINCT Employee
FROM [Source]
WHERE Employee NOT IN (SELECT EmployeeName FROM Employee)
INSERT INTO [BookEmployee] (BookID, EmployeeID, StartDate, EndDate)
SELECT Book.ID, Employee.ID, Source.StartDate, Source.EndDate
FROM [Source]
INNER JOIN Book ON Book.BookName = Source.Book
INNER JOIN Employee ON Employee.EmployeeName = Source.Employee
You could run those in a transaction if you're doing it a lot. You could also add in some MERGE behavior, but I wouldn't bother since you don't have anything more than one column to insert. I also didn't do anything as far as merging behavior is concerned for the last query, but I'm sure this will get you enough of a start to make it work.
But yeah, you won't be able to do it all "at once," per se, and even if you could, this way is significantly more readable than that would be.
I have a table to be imported from excel.It has an column called the sector table name "ExcelTable"
Name Title Sector
John manager Sofware
Sam Lawyer Jus
"ExcelTable" has 3284 rows.I create table called "SECTORS"."SECTORS" table's cloumn like this
SectorId SectorName
1 Sofware
2 Jus
It has 61 rows.
I inserted "EXCELTABLE" to "GLOBALCONTACTS".They has same rows number 3284 I want to insert "GLOBAL_CONTACTS" table sector by sectorid .It is now
ContactId Name Title Sector
1 John manager null
2 Sam Lawyer null
I want it to be like this
ContactId Name Title Sector
1 John manager 1
2 Sam Lawyer 2
I think you just want to join ExcelTable to Sectors for an INSERT:
INSERT INTO GLOBAL_CONTACTS (Name,Title,Sector)
SELECT e.Name,e.Title,s.SectorID
FROM ExcelTable e
INNER JOIN Sectors s
ON e.Sector = s.SectorName
Hi I have a table DataTable as :
Name Age Address
----------------
Tom 21 XYZ
John 23 X123
Sam 32 Y123
there is another table MappingTable :
Name Address
-------------
John A12345
Now I want to create a query that returns the following :
Name Age Address
----------------
Tom 21 XYZ
John 23 A12345
Sam 32 Y123
How can I do this. I tried joining the tables but that would replace the complete column. I cannot even use Update since I am only returning a view using this query.
Thanks,
Monica
select dt.name,
dt.age,
coalesce(mt.address, dt.address)
from DataTable dt
left join MappingTable mt
on mt.Name = dt.Name;