how to load specific attributes from two table to another? - sql

I am trying to load attributes from two tables to one table.
I have a Location table:
Id City State Country
===============================
1 New York New York USA
2 Portland Oregon USA
3 Tokyo Honshu Japan
And a User table:
Id First_Name Last_Name Hometown_City Hometown_State Hometown_Country
===========================================================================
1 Brett Burr New York New York USA
2 Bucky Beaver Portland Oregon USA
3 Ranma Saotome Tokyo Honshu Japan
I'm creating a new table for users, which instead of containing the separate Hometown fields, has a Hometown_Id foreign key.
Something like:
Id First_Name Last_Name Hometown_Id
========================================
1 Brett Burr 1
2 Bucky Beaver 2
3 Ranma Saotome 3
However, I'm having a problem with the syntax when inserting the data into the new Users table.
I can insert the non-location based fields easily with a command like:
INSERT INTO newusers (Id, First_Name, Last_Name)
SELECT DISTINCT Id, First_Name, Last_Name
FROM users
However, I'm not sure of the correct syntax to then add the values from the location table

Assuming that you have the appropriate constraints, and that the Location table contains unique entries, the following should work:
INSERT INTO newusers (Id, First_Name, Last_Name, Hometown_Id)
SELECT users.Id, users.First_Name, users.Last_Name, locations.Id
FROM users
INNER JOIN locations
ON locations.City = users.Hometown_City
AND locations.State = users.Hometown_State
AND locations.Country = users.Hometown_Country
If you have more than one location needed (such as a 'current residence' entry), alias and join to the locations table (from users) a second time.

Related

Multiple level lookup field

I have three tables, Countries, Department & Cities, Cities table contains a foreign key to Department table PK index, and Department contains a foreign key to Countries Table PK Index for example :
COUNTRIES TABLE RECORDS
PK=1 | NAME = France
DEPARTMENTS TABLE RECORDS
PK=1 | NAME=Ile de France | COUNTRYKEY=1
PK=2 | NAME=Bouches du Rhone | COUNTRYKEY=1
CITIES TABLE RECORDS
PK=1 | NAME=Paris | DEPTKEY=1
PK=2 | NAME=Marseille | DEPTKEY=2
So, i want display a city form with all details, name department country
I actually use lookup field to display the department name but what about to display also in the city form the "COUNTRY" name which is only included on Department Table as foreignkey ??? i mean is there a way to display a lookup field of a lookup field ? as a beginner a detailled code would be appreciated, Thanks to all
SELECT d.NAME AS Department_Name, ct.NAME as CITY, cn.NAME AS COUNTRY
FROM DEPARTMENTS d
LEFT JOIN CITIES ct ON d.PK = ct. DEPTKEY
LEFT JOIN COUNTRIES ON d.COUNTRYKEY = cn.PK
You might need an WHERE clause added and possibly a ORDER BY at the end, but you didn't indicate that.

Copy row with 2 different values into same table

I am having trouble getting a record to be copied and inserted into the same table but with different values and based on two conditions.
What I so Far:
INSERT INTO Userdetails
(ID, Username, Firstname, Surname, Location, TimeAs)
SELECT ID, Username, Firstname, Surname, Location, CURRENT_TIMESTAMP
FROM
Userdetails where Username = 'Harvard'; // and the latest date of the record
What I am trying to do is when a location is updated a new record with a new Timestamp and location with all the details of the old record (Firstname etc...) is inserted into the table, but keeping the old record.
If I just use the WHERE Username = I multiply the number of records each time the query is executed by 2x.
Sample Date:
Username | Firstname | Surname | Location | Last Updated
Harvard David Beckham London 2017-05-08 12:11:00
Harvard David Beckham Turkey 2017-05-08 12:14:00
Stanton John Smith Paris 2017-05-08 11:24:00
// This would be the result of the query, With a different timeStamp and Location but keeping the old record
Harvard David Beckham Hong Kong 2017-05-08 12:20:00
What I would like it to do is Copy the latest record where the username = 'Harvard' but also look use the latest time and not just the Username, as this would create 2 records not just the 1 I want.
Any help is appreciated.
Unless I'm missing something here, you can simply use top 1 with order by:
INSERT INTO Userdetails
(ID, Username, Firstname, Surname, Location, TimeAs)
SELECT TOP 1 ID, Username, Firstname, Surname, Location, CURRENT_TIMESTAMP
FROM Userdetails
WHERE Username = 'Harvard'
ORDER BY TimeAs DESC;

SQL Insert with value from different table

I have 2 tables storing information. For example:
Table 1 contains persons:
ID NAME CITY
1 BOB 1
2 JANE 1
3 FRED 2
The CITY is a id to a different table:
ID NAME
1 Amsterdam
2 London
The problem is that i want to insert data that i receive in the format:
ID NAME CITY
1 PETER Amsterdam
2 KEES London
3 FRED London
Given that the list of Cities is complete (i never receive a city that is not in my list) how can i insert the (new/received from outside)persons into the table with the right ID for the city?
Should i replace them before I try to insert them, or is there a performance friendly (i might have to insert thousands of lines at one) way to make the SQL do this for me?
The SQL server i'm using is Microsoft SQL Server 2012
First, load the data to be inserted into a table.
Then, you can just use a join:
insert into persons(id, name, city)
select st.id, st.name, c.d
from #StagingTable st left join
cities c
on st.city = c.name;
Note: The persons.id should probably be an identity column so it wouldn't be necessary to insert it.
insert into persons (ID,NAME,CITY) //you dont need to include ID if it is auto increment
values
(1,'BOB',(select Name from city where ID=1)) //another select query is getting Name from city table
if you want to add 1000 rows at a time that'd be great if you use stored procedure like this link

Insert a value based on id from two different tables

I got a huge question.
I'm trying to migrate some data from an existent table to a new one. I'm having troubles to figure out how to do the following :
In the Address table there are two columns:
AddressTable
---------------------------------------------
StateCode(nvarchar) and CountryCode(nvarchar)
Both hold a two letter code for states and countries codes.
Now in the new table we made two foreign keys
NewAddressTable
---------------------
StateId and CountryId
That correspond to two tables State and Country
StateTable has (Id,(FK)IdCountry,Name,Code)
CountryTable has (Id,Name,Code)
What I'm trying to do is based on the state and country code on the Address table how can I add replace the values from the old table with the new ones based on the state and code.
An example:
AddressTable
-------------
City StateCode PostalCode CountryCode
North Haven CT 06473 US
NewAddressTable
---------------
IdCountry IdState
236 8
CountryTable
---------------
Id Name Code
236 UNITED STATES US
StateTable
--------------
Id IdCountry Name Code
8 236 CONNECTICUT CT
Thank you.
Something like this should work.
insert into newtable
(idCountry, idState)
select country.id, state.id
from oldtable join country on oldtable.CountryCode = Country.Code
join state on oldtable.stateCode = state.code

UPDATE query that fixes orphaned records

I have an Access database that has two tables that are related by PK/FK. Unfortunately, the database tables have allowed for duplicate/redundant records and has made the database a bit screwy. I am trying to figure out a SQL statement that will fix the problem.
To better explain the problem and goal, I have created example tables to use as reference:
alt text http://img38.imageshack.us/img38/9243/514201074110am.png
You'll notice there are two tables, a Student table and a TestScore table where StudentID is the PK/FK.
The Student table contains duplicate records for students John, Sally, Tommy, and Suzy. In other words the John's with StudentID's 1 and 5 are the same person, Sally 2 and 6 are the same person, and so on.
The TestScore table relates test scores with a student.
Ignoring how/why the Student table allowed duplicates, etc - The goal I'm trying to accomplish is to update the TestScore table so that it replaces the StudentID's that have been disabled with the corresponding enabled StudentID. So, all StudentID's = 1 (John) will be updated to 5; all StudentID's = 2 (Sally) will be updated to 6, and so on. Here's the resultant TestScore table that I'm shooting for (Notice there is no longer any reference to the disabled StudentID's 1-4):
alt text http://img163.imageshack.us/img163/1954/514201091121am.png
Can you think of a query (compatible with MS Access's JET Engine) that can accomplish this goal? Or, maybe, you can offer some tips/perspectives that will point me in the right direction.
Thanks.
The only way to do this is through a series of queries and temporary tables.
First, I would create the following Make Table query that you would use to create a mapping of the bad StudentID to correct StudentID.
Select S1.StudentId As NewStudentId, S2.StudentId As OldStudentId
Into zzStudentMap
From Student As S1
Inner Join Student As S2
On S2.Name = S1.Name
Where S1.Disabled = False
And S2.StudentId <> S1.StudentId
And S2.Disabled = True
Next, you would use that temporary table to update the TestScore table with the correct StudentID.
Update TestScore
Inner Join zzStudentMap
On zzStudentMap.OldStudentId = TestScore.StudentId
Set StudentId = zzStudentMap.NewStudentId
The most common technique to identify duplicates in a table is to group by the fields that represent duplicate records:
ID FIRST_NAME LAST_NAME
1 Brian Smith
3 George Smith
25 Brian Smith
In this case we want to remove one of the Brian Smith Records, or in your case, update the ID field so they both have the value of 25 or 1 (completely arbitrary which one to use).
SELECT min(id)
FROM example
GROUP BY first_name, last_name
Using min on ID will return:
ID FIRST_NAME LAST_NAME
1 Brian Smith
3 George Smith
If you use max you would get
ID FIRST_NAME LAST_NAME
25 Brian Smith
3 George Smith
I usually use this technique to delete the duplicates, not update them:
DELETE FROM example
WHERE ID NOT IN (SELECT MAX (ID)
FROM example
GROUP BY first_name, last_name)