Avoid CASE clause while importing data to SQL Server - sql

I have to import data from an old schema to a new one, where a column 'career_name' (in table 'users') that used to be a VARCHAR now should be an INTEGER which is a foreign key to another table careers. This way I intend to tipify the data that was stored in the VARCHAR column in order to keep integrity in my database.
Actually, I do the following:
Create both new tables in the new schema
Use SELECT DISTINCT 'career_name' FROM old_table in order to obtain all possible values
INSERT into my new table careers the rows obtained above
INSERT data into my new table users using a CASE clause in order to obtain the ID from table careers of the corresponding former career_name so the relation is created.
Now the problem is the following, the table careers is big, so writing one CASE clause for each row in the table in order to import users is nearly impossible.
Is there a way to avoid this? I wish I could use my table careers as an associative array, where the key was the former career_name and the value the row's ID... Thanks!

INSERT into new_Users
SELECT Users.Name, careers.id
FROM Users inner join careers ON Users.career_name = careers.career_name
Because the schema isnt known to me, I am assuming that new_users table has 2 columns which is name and career_id.

Is there a way to avoid this? I wish I could use my table 'careers' as an associative array, where the key was the former 'career_name' and the value the row's ID... Thanks!
Er... That's what a table is, isn't it? Just join to your new careers table to use it as a lookup when doing the insert:
INSERT INTO users (blah, whatever, career_id)
SELECT
old_users_table.blah,
old_users_table.whatever,
careers.career_id
FROM
old_users_table INNER JOIN careers ON old_users_table.career_name = careers.career_name
... where users is your new users table, old_users_table is wherever you're getting the data you want to migrate, and careers is your new careers table.

Related

Assign unique ID to duplicates in Access

I had a very big excel spreadsheet that I moved into Access to try to deal with it easier. I'm very much a novice. I'm trying to use SQL via Access.
I need to assign a unique identifier to duplicates. I've seen people use DENSE_RANK in SQL but I can't get it to work in Access.
Here's what I'm trying to do: I have a large amount of patient and sample data (20k rows). My columns are called FULL_NAME, SAMPLE_NUM, and DATE_REC. Some patients have come in more than once and have multiple samples. I want to give each patient a unique ID that I want to call PATIENT_ID.
I can't figure out how to do this, aside from typing it out on each row. I would greatly appreciate help as I really don't know what I'm doing and there is no one at my work who can help.
To illustrate the previous answers' textual explanation, consider the following SQL action queries which can be run in an Access query window one by one or as VBA string queries with DAO's CurrentDb.Execute or DoCmd.RunSQL. The ALTER statements can be done in MSAcecss.exe.
Create a Patients table (make-table query)
SELECT DISTINCT s.FULL_NAME INTO myPatientsTable
FROM mySamplesTable s
WHERE s.FULL_NAME IS NOT NULL;
Add an autonumber field to new Patients table as a Primary Key
ALTER TABLE myPatientsTable ADD COLUMN PATIENT_ID AUTOINCREMENT NOT NULL PRIMARY KEY;
Add a blank Patient_ID column to Samples table
ALTER TABLE mySamplesTable ADD COLUMN PATIENT_ID INTEGER;
Update Patient_ID Column in Samples table using FULL_NAME field
UPDATE mySamplesTable s
INNER JOIN myPatientsTable p
ON s.[FULL_NAME] = p.[FULL_NAME]
SET s.PATIENT_ID = p.PATIENT_ID;
Maintain third-norm principles of relational databases and remove FULL_NAME field from Samples table
ALTER TABLE mySamplesTable DROP COLUMN FULL_NAME;
Then in a separate query, add a foreign key constraint on PATIENT_ID
ALTER TABLE mySamplesTable
ADD CONSTRAINT PatientRelationship
FOREIGN KEY (PATIENT_ID)
REFERENCES myPatientsTable (PATIENT_ID);
Sounds like FULL_NAME is currently the unique identifier. However, names make very poor unique identifiers and name parts should be in separate fields. Are you sure you don't have multiple patients with same name, e.g. John Smith?
You need a PatientInfo table and then the SampleData table. Do a query that pulls DISTINCT patient info (apparently this is only one field - FULL_NAME) and create a table that generates unique ID with autonumber field. Then build a query that joins tables on the two FULL_Name fields and updates a new field in SampleData called PatientID. Delete the FULL_Name field from SampleData.
The command to number rows in your table is [1]
ALTER TABLE MyTable ADD COLUMN ID AUTOINCREMENT;
Anyway as June7 pointed out it might not be a good idea to combine records just based on patient name as there might be duplicates. Better way will be treat each record as unique patient for now and have a way to fix patient ID when patient comes back. I would suggest to go this way:
create two new columns in your samples table
ID with autoincrement as per query above
patientID where you will copy values from ID column - for now they will be same. But in future they will diverge
copy columns patientID and patientName into separate table patients
now you can delete patientName column from samples table
add column imported to patients table to indicate, that there might be some other records that belong to this patient.
when patients come back you open his record, update all other info like address, phone, ... and look for all possible samples record that belong to him. If so, then fix patient id in those records.
Now you can switch imported indicator because this patient data are up to date.
After fixing patientID for samples records. You will end up with patients with no record in samples table. So you can go and delete them.
Unless you already have a natural key you will be corrupting this data when you run the distinct query and build a key from it. From your posting I would guess a natural key would be SAMPLE_NUM. Another problem is that if you roll up by last name you will almost certainly be combining different patients into one.

SQL inserting rows from multiple tables

I have got an assignment. We have been given a table, MAIN_TABLE, which has a column patient_id as foreign key.
I need to make a separate table named patient which has patient_id as a primary key along with some other attributes such as name and address.
I did successfully create schema of this table. Now there is a serious problem I am facing. After creating this table I used insert statement to insert values for name and address from a dummy table.
Till this point everything works fine. However, the column patient_id is still empty rather I have set it to 0 by default.
Now the problem is that I need to get values into this column, patient_id, from the patient_id column of MAIN TABLE.
I can't figure out how do I do this? I did try to use:
UPDATE patient
SET patient_id=(select id from MAIN_TABLE)
BUT this gives me error that multiple rows returned which does make sense but what condition do I put in where clause then?
That sounds strange. How can there be a table MAIN_TABLE with a foreign key patient_id but the master table patient does not exist. Where do that patient_ids in MAIN_TABLE come from?
I suggest not to insert your data from a dummy table alone and then try to update it. But insert it with both - the MAIN_TABLE and the dummy table joined. If you can not join them. You would also not be able during the update.
So since i think they have no connected primary/foreign keys the only way to join them is using a good business key. Do you have a good business key?
You are talking about persons. So First Name, Last Name, Birth Day, Address often is good enough. But you have to think about it.
With your given data I can only give you some kind of meta insert statement. But you will get the point.
Example:
insert into patient (col1, col2, col3)
select
a.colA,
a.colF,
b.colX
from
dummy_table a
inner join MAIN_TABLE b on a.colN=b.colA and a.colM=b.colB
And: If patient_id is your primary key in patient you should ensure that it is even not possible to have duplicate values or null in this column. And you should use constraints to ensure your data integrity.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm

Retrive unique records from an access table which does not have a fixed structure

I want only the unique records in same or new table. And I want to do this with different tables (having duplicate records) in access database through same code.
The flow should be like:
input table ------VBA MODULE------> table with unique records
I am able to do this group by function but for that i have to use field names in query. But field names will differ from table to table.
Please help!
Just use query
SELECT DISTINCT * FROM MyAnyTable

Copy records missing from one table to a new table

I managed to delete 4,000 rows from a table in my 129,000-row production database (Postgres 9.4 on Heroku), but only identified the problem a few days later.
I have a backup from before the loss, but only want to selectively restore the missing rows back to the table, preserving their id's. (A complete restore is not an option as new data has since been added to the table.)
Into a local testing database I have imported the backed-up table as articles_backup, alongside the actual articles table. I want to find all the rows in articles_backups that are missing from articles and then copy these to a new table articles_restores that I will then restore to the production database, back into the articles table (preserving record id's).
This query successfully returns all the id's of the deleted records:
select articles_backups.id
from articles_backups
left outer join articles on (articles_backups.id = articles.id)
where articles.id is null
But I have not been able to copy the result to a new table. I have unsuccessfully tried:
select *
into articles_restores
from articles_backups
left outer join articles on (articles_backups.id = articles.id)
where articles.id is null;
Which gives:
ERROR: column "id" specified more than once
Basically your query with LEFT JOIN / IS NULL does what you are after:
Select rows which are not present in other table
You get the error because you select all columns from both tables, and there is an id column in both. It's not possible to create a new table with duplicate column names, and it's not what you want to begin with. Only select columns from articles_backups:
CREATE TABLE articles_restores AS
SELECT ab.*
FROM articles_backups ab
LEFT JOIN articles a USING (id)
WHERE a.id IS NULL;
While being at it I simplified your query syntax with table aliases. The USING clause is just for the convenience of shorter code. It folds the two id columns into one, but all other columns are still in there twice if you SELECT *.
Use CREATE TABLE AS. SELECT INTO is also defined by the SQL standard and implemented in Postgres, but its use is discouraged. It's used in PL/pgSQL functions for a different purpose. Details:
Creating temporary tables in SQL
You could use an except to retrieve all the rows from articles_backup that are different from articles:
(assuming both tables have the same columns in the same order)
you could also create a temp table with this info to make it easy on your repairing statements:
create table temp_articles as
select * from articles_backup
except
select * from articles
step 1 - update rows from 'articles_backup' present in articles.
This step needs attention... you will have to establish a rule to choose between the data present in articles and the one present in temp_articles.
UPDATE articles a
SET a.col1=b.col1,
a.col2=b.col2,
(... other columns ...)
FROM (SELECT * FROM temp_articles) AS b
WHERE a.id = b.id and /* your rule for data to be (or not) updated goes here */
step 2 - insert rows from 'articles_backup' not present in articles (your deleted records):
insert into articles
select * from temp_articles where id not in (select id from articles)
Let us know if you need more help.

SQL - Selecting a field from another table using a primary key in a trigger

I have two tables in my database, one is Transactions and the other is TransactionHistories. The latter is essentially an auditing table, whereby a trigger executes on insert, update and delete on Transactions to capture a screenshot of the data.
I am successfully retrieving all of the data stored in the Transactions table where the columns match, but the difficulty comes where I am trying to retrieve data from another table using a foreign key. For instance:
The transaction table has a field "TransactionType_TransactionTypeId", but in the audit table we wish to store its 'name' equivalent as "TransactionTypeName". This needs to be populated from the "TransactionTypes" table, which has the fields "TransactionTypeId" and "Name".
I am struggling to write a query to retrieve this as we wish. I am trying something similar to the following but having little success:
SELECT #TransactionTypeName=Name
FROM TransactionTypes
WHERE inserted.TransactionType_TransactionTypeId=TransactionTypes.TransactionTypeId;
I'm assuming that is a syntactic nightmare. If someone could point me in the right direction I would be extremely grateful!
well to get a name you should do the following
select #TransactionTypeName = TT.Name
from inserted as i
left outer join TransactionTypes as TT on TT.TransactionTypeId = i.TransactionType_TransactionTypeId
but you have to know that inserted table can have more than one row, and you are getting value for only one row.