Copy row with 2 different values into same table - sql

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;

Related

Historical sql Table With Bits Of User Information - Make New Table With 1 Entry & All Information

I have a table (customers) that has 43 columns of user information (first name, last name, address, city, state, zip, phone, email, visitDate, lastActive, etc...)
Every night, I'm getting a feed from our clients with the customers that visited them that day. These visits are stored into the customers table without removing the old record. The old record is marked lastActive = 0 and the new one is marked lastActive = 1. Any null fields are stored as "Unknown".
Obviously this results in a very large table that takes a while to query. So, I plan on making a new table that is only the distinct users and their most complete information.
For example: If Bob Smith was imported on January 1st with no phone or email, and then he was imported again on August 1st with a phone, but no email, and then imported again on September 1st with no phone, but an email, my customers table would look something like this:
CustImportID CustomerKey FirstName LastName Phone Email visitDate lastActive
1 1 Bob Smith Unknown Unknown 2016-01-01 0
2 1 Bob Smith 5551231234 Unknown 2016-08-01 0
3 1 Bob Smith Unknown 1#2.io 2016-09-01 1
So my question is this, what's the best way to get the distinct people from the customers table, and insert them into the new table where Bob would only be one entry, but I would have values for every field (if every entry has phone, for example, we would pull the phone from the most recent entry), resulting is something like this:
CustomerKey FirstName LastName Phone Email visitDate
1 Bob Smith 5551231234 1#2.io 2016-09-01
You can use FIRST_VALUE with a trick to ignore 'Uknown' values:
SELECT FirstName, LastName,
FIRST_VALUE(Phone) OVER (ORDER BY CASE
WHEN Phone='Unknown' THEN 1
ELSE 0
END,
visitDate DESC) AS Phone,
FIRST_VALUE(Email) OVER (ORDER BY CASE
WHEN Email='Unknown' THEN 1
ELSE 0
END,
visitDate DESC) AS Email
FROM mytable
FIRST_VALUE is available from SQL Server 2012. It picks the latest field value as specified by the ORDER BY of the OVER clause. Due the CASE in the ORDER BY clause, 'Unknown' values will have to lowest priority.
you can use max of values from all records which will result this:
select customerkey, max(firstname), max(lastname), max(phone), max(email), max(visitdate) from yourtablename
If you have two are more valid entries then use row_number and select max of that based on recent values

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

Select Specific value from a table

ID FName Lname Status Major Code GPA Admitted Date
101 Tom Smith Freshman 103 3.51 3-May-2015
I have a table with these columns, I need to "list the sophomores who were admitted before 2015" Now I've got the admitted before 2015 part down, but I am struggling with selecting only sophomores throughout this large table.
I'm thinking I'll need to use DISTINCT or WHERE IN but I'm not sure how to select sophomore as the table doesn't recognize that
SELECT status, fname, lname, gpa, admitteddate
FROM mytablename
WHERE status = 'JUNIOR' AND
TO_CHAR(admitteddate, 'YYYY') <=2014;
This is the correct query, thank you!
I assume the Status column is the one with the key information. If you have rows with Sophomore in this column, it is as simple as adding Status = 'Sophomore' to the WHERE clause.

SQL Insert trigger access old values cleanly?

I'm new to SQL beyond basic queries / inserts (as you'll see quickly as you read further)
Here's a (very) simplified example.
I have table 'person' like:
UID | NAME | AGE | LOCATION
45 | bob | 23 | Canada
31 | bill | 20 | Romania
and a second table 'person_history' like:
UID | PID | NAME | AGE | LOCATION
- | - | - | - | -
when I insert into this table like
update person set age=10 where UID==45
I want my trigger to fire, to access the existing values in person, and to push them into the second table, and then continue with the original insert.
The way I can think to do this is:
Select uid, name, age, location,
into v_uid, v_name, v_age, v_location
from person
where uid = :new.uid
then do the insert like
Insert into person_history(UID, PID, NAME, AGE, LOCATION)
VALUES (sequence.nextval, v_uid, v_name, v_age, v_location);
but this seems like a very round-about way of doing it - especially if the table has 50 columns.
Is this the correct method, and is there a more elegant way of approaching this problem.
Again, keep in mind how new I am to all of this, so examples would be really helpful.
why do you do this part?:
Select uid, name, age, location,
into v_uid, v_name, v_age, v_location
from person
where uid = :new.uid
Just use this approach:
INSERT INTO person_history(UID, PID, NAME, AGE, LOCATION)
VALUES (sequence.nextval, ::new.uid, ::new.name, ::new.age, ::new.location);
Regarding the quantity of columns, I'm not sure it is possible to do it in a "smarter" way.

how to load specific attributes from two table to another?

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.