Set column value to foreign key based on another column - sql

I am using SQL Server and have imported data from an Excel file into my tables.
My tables consist of:
BH_Overview (foreign key table) BH_OverView Table
BH_Equipment (primary key table) BH_Equipment Table
I have different types of equipment and looking to split it out into its own table called BH_Equipment and link it into the main table BH_Overview.
I have my tables created and constraints made, however when data is imported into table I have just stored the equipment name in the the BH_Overview table in a column "Equipment" that isn't link with BH_Equipment.
I'm wondering how I go about updating the equipmentId column based on what is in the equipment column in the BH_Overview table to match the Id in the BH_Equipment table.
You can see I have the foreign keys done for Factory Area and responsibility and that was done manually with update statement as only a few foreign keys to link but with equipment there is 291 types in the BH_Equipment table.
I have tried a update and inner joins, but can't get my head around it. Apologies if I have went about this an awful way, relatively new to SQL so please show if there is a much easier way or if this has been asked before please link and ill give it a look.
UPDATE:
#Charlieface - error message appearing

The other answer is good, but for SQL Server you can update much more easily directly through a join:
update o
set equipmentId = e.id
from BH_OverView o
join BH_Equipment e on e.equipment = o.Equipment;
This rough syntax also works on Postgres, MySQL/MariaDB and the later versions of SQLite.

First, you should have the content of the column Equipment in the table BH_OverView match one of column equipment content in the table BH_Equipment
Then by the following SQL statement, you populate the corresponding equipmentId in the table BH_OverView
update BH_OverView
set equipmentId = (select id from BH_Equipment
where BH_Equipment.equipment=BH_OverView.Equipment)
after verifying the content of equipmentId in the table BH_OverView, you may drop the column Equipment from the table BH_OverView by
alter table BH_OverView drop column Equipment
I am using standard SQL which should operate on the majority of Databases.
Based on your comment
you got an error message
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
This means that in your table BH_Equipment, you have one more equipment that has the same name. You have repeated equipment name in rows of the table BH_Equipment
to get this equipment and the number of time they exist, use the following SQL statement
select equipment, count(id)
from BH_Equipment
group by equipment
having count(id)>1
delete one of the repeated rows, then the error message will not exist.

Related

one-to-one tables relationship, linked by the autonumber in the main table

I have a main table that contain the customers details, I built another table that contain for example a yes/no fields about if the customer paid his taxes, the two tables is linked with autonumber from the main table.
I want always to keep them both with the same amount of records (that means every customer has a record in the second table even if the second table has empty record with data only in the primary key field)
I need that cause with missing records I cannot run update query to auto fill the second table and i got an error of validation rule violation.
I use this sql:
update clients LEFT JOIN MonthlyTbl ON clients.SerialNo = MonthlyTbl.serialno
set sReport04='ready';
I have almost 700 records in the main table and only 80 records in the second, and when I run the sql it updates only 80!!!!
Thanks for Help
Please use below query,
update clients set sReport04='ready' where SerialNo in
(select serialno from MonthlyTbl);
here is the right answer
first run the sql:
INSERT INTO monthlytbl ( serialno )
SELECT clients.serialno FROM clients
WHERE (((clients.[serialno]) Not In (select serialno from monthlytbl)));
and then:
select sreport04 from monthlytbl
set sReport04='ready';

SQL query to insert IDs in tables

I will try to be short and concise, I have this table which contains rows of data.
I also have 3 separate tables, Surgery, TypeOfSurgery and Procedure, each filled with additional data, and each should contain the Id (foreign key) to the previous table.
For example TypeOfSurgery has a FK column SurgeryId, Procedure has FK column TypeOfSurgeryId etc, I need to update the existing entries in these tables!
And I also have 3 dropdowns, each connected to the previous one.
EXPECTED OUTPUT:
If I choose Abdominal Surgery the following dropdown should be populated with Appendectomy and Caesarian Section, further if I choose Appendectomy the next dropdown should be populated with procedure A, and if I choose Caesarian section the next dropdown should contain procedure B and Procedure C etc...
My question is how do I give the corresponding IDs to each row in each table with one query, so the dropdowns will work as I described above.
Thanks!
It sounds like you're asking how to decompose this denormalised data into three different tables.
This is how I would do it.
(I wouldn't normally answer a question where the post doesn't contain DDL)
First ensure that all three target tables have an identity field defined against the PK so that keys are autogenerated.
Populate Surgery. SurgeryID in this table must be IDENTITY
INSERT INTO Surgery (SurgeryName)
SELECT DISTINCT Surgery FROM YourTable
Populate TypeOfSurgery. TypeOfSurgeryId must be IDENTITY
INSERT INTO TypeOfSurgery (SurgeryID, TypeOfSurgeryName)
SELECT DISTINCT S.SurgeryID, SRC.TypeOfSurgery
FROM YourTable SRC
INNER JOIN Surgery S
ON S.SurgeryName = SRC.Surgery
Populate Procedure. ProcedureId must be IDENTITY
INSERT INTO Procedure (TypeOfSurgeryId, ProcedureName)
SELECT DISTINCT S.TypeOfSurgeryId, SRC.Procedure
FROM YourTable SRC
INNER JOIN TypeOfSurgery S
ON S.TypeOfSurgeryName = SRC.TypeOfSurgery

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.

How to determine if a column exists in SQL server DB in other tables with a different name

I need to fetch specific hardware data from source tables. The hardware information is present in a table Server_Data with columns as follows,
Server_ID, Server Property, Property_Value
65 Model Cisco 123
65 Name Cisco abc
I need to link this table with System table that has columns as follows,
System_ID, System_IP
1 10.20.30.40
I searched all tables in database but Server_ID column is present only in Server _Data table. Also, I searched all tables if there exists a table that links System_ID with Server_ID, but there is no such table.
I need to find if the Server_ID column is present in any other table with some other name (say Server_Key or just Key). Any help would be appreciated.
Only using SQL, there will not be a way to find an identical column in another table, especially if it has a different name. I think you would need to manually compare every column in every other table to that column to find a match.
If I were you I would start by running the following SP:
EXEC sp_fkeys 'Server_Data'
That will tell you if the Server_ID column is referencing any other table in the DB or not.

Update all rows of a single column

I'm dealing with two tables which have 2 columns, as listed under.
Table 1: table_snapshot
account_no | balance_due
Table 2: table_ paid
account_no | post_balance | delta_balance
I added a third column to table2 with the following command:
ALTER TABLE table_paid ADD delta_balance number(18);
I'm trying to use the following query, to update the new column ( delta_balance ) with the difference in balances between 1 and 2.
FYI, table_paid is a subset of table_snapshot. i,e., table 2 has only a few accounts present in table 1. I get an error saying : SQL Statement not properly ended. the query i'm using is:
UPDATE table_paid
SET table_paid.delta_balance = table_paid.post_balance - table_snapshot.balance_due
from table_paid, table_snapshot
WHERE table_paid.account_no = table_snapshot.account_no;
Appreciate if someone can correct my query.
Many thanks.
novice.
Oracle doesn't have the UPDATE ... FROM syntax that you're using from MS Sql Server (which, I believe, isn't ANSI anyway). Instead, when you need to do an update on a result set, Oracle has you create the resultset as a kind of inline view, then you update through the view, like so:
UPDATE ( SELECT tp.delta_balance
, tp.post_balance
, ts.balance_due
FROM table_paid tp
JOIN table_snapshot ts
ON tp.account_no = ts.account_no
)
SET delta_balance = post_balance - balance_due;
This is more "correct" than the answers supplied by Babar and palindrom, as their queries will update every row in table_paid, even if there are no corresponding rows in table_snapshot. If there is a 1-1 correspondance, you don't need to worry, but it's safer to do it with the inline view.
It's unclear from your example which table is the parent table, or (as I'm guessing) neither is the parent table and account_no is pointing to the primary key of another table (presumably account, or "table_account" by your naming conventions). In any case, it's clear that there is not a 1-1 correspondence in your table - 15K in one, millions in the other.
This could mean 2 things: either there are many rows in table_snapshot that have no corresponding row in table_paid, or there are many rows in table_snapshot for each row in table_paid. If the latter is true, your query is impossible - you will have multiple updates for each row in table_paid, and the result will be unpredictable; how will you know which of the "post_balance - balance_due" expressions will ultimately determine the value of a given delta_balance?
If you run my query, you will find this out quickly enough - you will get an error message that says, "ORA-01779: cannot modify a column which maps to a non key-preserved table". This error will appear based not on the data in the table (it may be okay), but based on the primary keys you have defined on the two tables. If the join condition you specify doesn't unambiguously result in a 1-1 relationship between the updated table and the rest of the join, based on the defined keys, you will get this error. It's Oracle's way of telling you, "You're about to screw up your data".
In the other answers here, you will only get an error (in that case, ORA-01427: single-row subquery returns more than one row) if you actually have data that would cause a problem; my version is more strict, so it may turn out that you will need to use the other versions.
And, as the others have said, you'll definitely want an index on account_no for the table_snapshot table. One on the table_paid wouldn't hurt either.
Try this
UPDATE table_paid
SET table_paid.delta_balance = table_paid.post_balance -
(SELECT table_snapshot.balance_due from table_snapshot WHERE table_paid.account_no =
table_snapshot.account_no);
UPDATE table_paid
SET table_paid.delta_balance = table_paid.post_balance - ( select balance_due from table_snapshot
WHERE table_paid.account_no = table_snapshot.account_no )