update table from another table's data - sql

I have 2 tables : customers (customer,city_name,postal_code) and postal_codes(city_name,postal_code).
In the customers table the postal_code entries are missing but the city is there.
How can I update the customers table from the postal_codes table so the missing postal_code gets updated in the customers table where the postal_code is missing?
This may be a duplicate but I could not make work any of the suggestions from similar threads. They all use some kind of abbreviations for table names which I find hard to follow.
Tried this but it does not seem to work :
UPDATE customers
SET postal_code = postal_codes.postal_code
FROM postal_codes.postal_code INNER JOIN postal_codes.city_name ON customers.city_name

As far as I recall SQLite does not support the update ... from join syntax, but this query should work for you:
UPDATE customers
SET postal_code = (
SELECT postal_codes.postal_code
FROM postal_codes
WHERE postal_codes.city_name = customers.city_name
)
WHERE EXISTS (
SELECT *
FROM postal_codes
WHERE postal_codes.city_name = customers.city_name
AND postal_codes.postal_code <> customers.postal_code
);

Related

Why won't this query update the field with the lookup?

I'm trying to run the following query to update one table from another. The dates and email address work and carry across, but the nested query I'm using to get Subject_1 from a reference table does not. What am I doing wrong?
SELECT
FirstRegistered As SignUpdate,
(SELECT Subj_ClusName FROM tblSubjectLookup INNER JOIN PAD_ApplicantLost2000 ON tblSubjectLookup.Subj_Name=PAD_ApplicantLost2000.raw_subj_interest_1) AS Subject_1,
Email_Address
FROM PAD_ApplicantLost2000
The origin table, PAD_ApplicantLost2000, has a 'raw subject' column which contains, for example, 'Biology'. There is another table, tblSubjectLookup, which has codes for all subjects, so Subj.Name has 'Biology' and 'Subj_ClusName' has 'B1', which is what needs to go in my target table. However, the Subject_1 field in the target table does not populate.
What am I doing wrong?
Why not just use a WHERE clause instead of joining the table again. I also added LIMIT 1 just to make sure only 1 value is returned.
SELECT
FirstRegistered As SignUpdate,
(SELECT Subj_ClusName FROM tblSubjectLookup WHERE tblSubjectLookup.Subj_Name = PAD_ApplicantLost2000.raw_subj_interest_1 LIMIT 1) AS Subject_1,
Email_Address
FROM PAD_ApplicantLost2000
Another, possibly better, way to do it would just be to join the table directly.
SELECT
FirstRegistered As SignUpdate,
Subj_ClusName AS Subject_1,
Email_Address
FROM PAD_ApplicantLost2000
LEFT JOIN tblSubjectLookup ON tblSubjectLookup.Subj_Name = PAD_ApplicantLost2000.raw_subj_interest_1

I'm trying to update a table with information based on another table

I have a table with a list of SSNs (not real ones) connected to houseIDs.
I need to update a specific SSN's houseid based on a given address.
I have another table with houseIDs connected to HouseAddresses.
Here is what I have so far:
update persons
set houseid = houses.houseid
from houses
where houses.houseaddress = 'Alma Street'
and persons.SSN = 675849512;
While this works, it doesn't update anything, and I know it should update one row.
I'm afraid I don't know where to go from here.
Try to use this
update persons
set persons.houseid = houses.houseid
from houses
where houses.houseaddress = 'Alma Street' and
persons.SSN = 675849512;
OR
update persons
set houseid = i.houseid
from (
select houseid,houseaddress
from houses) i
where i.houseaddress = 'Alma Street' and
persons.SSN = 675849512;
if you want to update your houseid from other table connected by address you should join tables by addresses
Look this
update persons
set houseid = (Select Top(1) houses.houseid from
from houses
where houses.houseaddress = persons.address
.....
);
TRY IN THIS WAY: Use JOIN for effective solution in the following way but in the below code I am taking SSN as the common column but you can replace it with one if different:
UPDATE p SET houseid = h.houseid
FROM persons p
INNER JOIN houses h ON h.SSN = p.SSN
AND h.houseaddress = 'Alma Street'
AND ----------
--------
You can add more conditions according to you requirement in AND or add WHERE clause if required.

Update in join query with 3 tables

I have problem with updating query in Access. I have 3 tables:
City
ID | CityName | CountryID|
Country
ID | CountryName
CityImport
City | Country
I'm not sure if it's the right design, but it's of a lesser importance now.
I want to update my db with Excel data. I decided to create CityImport table to make the process clearer. I put city information in this table and I want fill City table with it. When I run a query like UPDATE (CityImport INNER JOIN Country ON CityImport.Country = Country.CountryName) LEFT JOIN City ON City.CityName = CityImport.City AND City.CountryID = Country.ID SET City.CityName = CityImport.City, City.CountryID = Country.ID WHERE CityImport.City IS NOT NULL, I get JOIN expression not supported error.
I thought it was a problem with my syntax, but if I remove one condition from JOIN, and leave it as UPDATE (CityImport INNER JOIN Country ON CityImport.Country = Country.CountryName) LEFT JOIN City ON City.CityName = CityImport.City SET City.CityName = CityImport.City, City.CountryID = Country.ID WHERE CityImport.City IS NOT NULL, it works fine. The problem is that it ignores cities with the same name in different countries.
Is it possible to make such join work properly somehow? Or is it incorrect by definition? It requires to join one one table with another join results on two columns from different tables. I could probably work around it somehow in this case, but I want to use the same method for more, more complicated tables.
I played around with different takes on this query for few hours, googled hundred times, but still no success.
The first problem I can see is that you're using UPDATE to insert data into a table. You should be using INSERT INTO.
Starting with this table:
You'll need to insert the unique Country names into the country table first:
INSERT INTO Country (Country)
SELECT DISTINCT Country
FROM CityImport
This will give you this table:
Now you need to populate the City table with city names and the ID's from the Country table:
INSERT INTO City (CityName, CountryID)
SELECT City, Country.ID
FROM CityImport INNER JOIN Country ON CityImport.Country = Country.Country
This returns this table:
Edit:
Table Structure:
CityImport
City - Text
Country - Text
Country
ID - AutoNumber
Country - Text
Primary Key: ID
City
ID - AutoNumber
CityName - Text
CountryID - Number
Primary Key: ID
Foreign Key CountryID References Country

How to prevent from updating the record in sql which is used in another table?

Tables
Country (country_id, country_name)
Company (company_id, country_id, Company_name)
How to prevent updating the row in the country table which is used in Company table?
UPDATE country SET your_values_here
WHERE
countryId = 123 AND
NOT EXISTS (SELECT 1 FROM Company WHERE countryId = 123)
You will have to use stored procedure to do that, Here's the pseudo code:
First, check if the countryID exists in Company
select 1 from Company where country_id = #country_id
If exist, throw an error, else do update:
update country set your_values_here
Company::country_id is just a posted foreign key so an update to one table shouldn't affect the other.
Are you talking about insertions or deletes? If so you would either alter Company so that country_id can be null (i.e. not requiring a corresponding record in Country table) or you would turn off cascading deletes.
Hopefully one of those and Google will sort it for you.

Insert data and set foreign keys with Postgres

I have to migrate a large amount of existing data in a Postgres DB after a schema change.
In the old schema a country attribute would be stored in the users table. Now the country attribute has been moved into a separate address table:
users:
country # OLD
address_id # NEW [1:1 relation]
addresses:
id
country
The schema is actually more complex and the address contains more than just the country. Thus, every user needs to have his own address (1:1 relation).
When migrating the data, I'm having problems setting the foreign keys in the users table after inserting the addresses:
INSERT INTO addresses (country)
SELECT country FROM users WHERE address_id IS NULL
RETURNING id;
How do I propagate the IDs of the inserted rows and set the foreign key references in the users table?
The only solution I could come up with so far is creating a temporary user_id column in the addresses table and then updating the the address_id:
UPDATE users SET address_id = a.id FROM addresses AS a
WHERE users.id = a.user_id;
However, this turned out to be extremely slow (despite using indices on both users.id and addresses.user_id).
The users table contains about 3 million rows with 300k missing an associated address.
Is there any other way to insert derived data into one table and setting the foreign key reference to the inserted data in the other (without changing the schema itself)?
I'm using Postgres 8.3.14.
Thanks
I have now solved the problem by migrating the data with a Python/sqlalchemy script. It turned out to be much easier (for me) than trying the same with SQL. Still, I'd be interested if anybody knows a way to process the RETURNING result of an INSERT statement in Postgres SQL.
The table users must have some primary key that you did not disclose. For the purpose of this answer I will name it users_id.
You can solve this rather elegantly with data-modifying CTEs introduced with PostgreSQL 9.1:
country is unique
The whole operation is rather trivial in this case:
WITH i AS (
INSERT INTO addresses (country)
SELECT country
FROM users
WHERE address_id IS NULL
RETURNING id, country
)
UPDATE users u
SET address_id = i.id
FROM i
WHERE i.country = u.country;
You mention version 8.3 in your question. Upgrade! Postgres 8.3 has reached end of life.
Be that as it may, this is simple enough with version 8.3. You just need two statements:
INSERT INTO addresses (country)
SELECT country
FROM users
WHERE address_id IS NULL;
UPDATE users u
SET address_id = a.id
FROM addresses a
WHERE address_id IS NULL
AND a.country = u.country;
country is not unique
That's more challenging. You could just create one address and link to it multiple times. But you did mention a 1:1 relationship that rules out such a convenient solution.
WITH s AS (
SELECT users_id, country
, row_number() OVER (PARTITION BY country) AS rn
FROM users
WHERE address_id IS NULL
)
, i AS (
INSERT INTO addresses (country)
SELECT country
FROM s
RETURNING id, country
)
, r AS (
SELECT *
, row_number() OVER (PARTITION BY country) AS rn
FROM i
)
UPDATE users u
SET address_id = r.id
FROM r
JOIN s USING (country, rn) -- select exactly one id for every user
WHERE u.users_id = s.users_id
AND u.address_id IS NULL;
As there is no way to unambiguously assign exactly one id returned from the INSERT to every user in a set with identical country, I use the window function row_number() to make them unique.
Not as straight forward with Postgres 8.3. One possible way:
INSERT INTO addresses (country)
SELECT DISTINCT country -- pick just one per set of dupes
FROM users
WHERE address_id IS NULL;
UPDATE users u
SET address_id = a.id
FROM addresses a
WHERE a.country = u.country
AND u.address_id IS NULL
AND NOT EXISTS (
SELECT * FROM addresses b
WHERE b.country = a.country
AND b.users_id < a.users_id
); -- effectively picking the smallest users_id per set of dupes
Repeat this until the last NULL value is gone from users.address_id.