Update in join query with 3 tables - sql

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

Related

Sql-server: update all rows columns based on IP

I have a table LogPixelCall(example of two rows):
1 d5104006-8a82-4dfe-b6ca-587d25e869e9 1 2 2016-03-07 16:31:41.997 **92.26.242.166** NULL
2 5a5ffea2-3a70-4138-aeb7-4dd94900ef27 1 2 2016-03-07 17:39:57.557 **185.28.19.174** NULL
where bolded is IP, and last NULL field is CountryId from other table.
Now I have Iplookup table, where I have to pass converted IP to long(so I have to use that conversion algorithm) and it returns me CountryCode (GB, US, AU), then I compare CountryCode with Country table, where I store countries. I want to then update LogPixelCall information table manually with CountryId, because this was missing before.
Question: Based on provided database schema, how do I update LogPixelCall CountryId NULL field, if I know ClientIp in LogPixelCall, and I can use IpLookup to get CountryIsoCode and connect with Country?
update LogPixelCall set CountryId = c.Id
--select * /*Check first to make sure */
from LogPixelCall lpc
inner join IpLookup ip on lpc.ClientIp between ip.From and ip.To
inner join Country c on c.Code = ip.CountryIsoCode

Join master table's data to a key/value table data in one SELECT

I have a table called Contacts that contains the columns
Id
FirstName
LastName
I have another table called ContactsExtra. It has the following columns:
Id
ContactId (FK refers to Contacts Id)
PropertyId (FK refers to Properties Id)
PropertyValue
This is a Key/Value table that stores some extra contact properties. E.g. if contact has a Salary property there is a record in this table for all Contacts that stores the Salary value.
All Properties (whether they are in the main Contacts table or not) are stored in a separate table called Properties. In this table, those properties that come from Contacts (FirstName and LastName) are locked. But the user can add or remove custom properties (these ones are not locked). The value of these new properties will be stored in ContactsExtra.
The Properties table contains the following columns:
Id
Name
What I would like to do is to display all the contact information using one SELECT. So e.g. in the above case there will be a result with columns Id,FirstName,LastName and also Salary. The first three come from Contacts and the last comes from the Key/Value table. How can I join these information together?
SELECT
Contacts.FirstName,
Contacts.LastName,
Properties.Name,
ContactsExtra.PropertyValue
FROM
Contacts
LEFT OUTER JOIN ContactsExtra ON Contacts.Id = ContactsExtra.ContactId
LEFT OUTER JOIN Properties ON ContactsExtra.PropertyId = Properties.Id
Okay, here's the update with a PIVOT (not UNPIVOT as I first thought)...
SELECT
*
FROM
(
SELECT
Contacts.FirstName,
Contacts.LastName,
Properties.Name,
ContactsExtra.PropertyValue
FROM
Contacts
LEFT OUTER JOIN ContactsExtra ON Contacts.Id = ContactsExtra.ContactId
LEFT OUTER JOIN Properties ON ContactsExtra.PropertyId = Properties.Id
) DerivedPivotable
PIVOT
(
MAX(PropertyValue)
FOR [Name] IN (<comma delimited list of values from your Properties.Name field, without string markup>)
--FOR [Name] IN (Salary, Height, Status, SSN) --example row
) Pivoted
Please check against your data - I expect the output to be something like...
FirstName LastName Salary Height Status SSN
-----------------------------------------------------------
Jane Doe NULL 5'7" Single NULL
Bob Smith 70,000 6'1" NULL 123-45-6789
The use of MAX is a bit of a kludge because it has to be an aggregate function there. The assumption is being made that there is only one value in the ContactsExtra table for each combination of user and property.

update table from another table's data

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
);

User to location mapping with country state and city in the same table

I have a user table that has among others the fields CityId, StateId, CountryId. I was wondering if it was a good idea to store them[City, State, Country] in separate tables and put their respective ids in the User table or put all the three entities in one table.
While the former is conventional, I am concerned about the extra tables to join and so would want to store all these three different location types in one table like so
RowId - unique row id
LocationType - 1 for City, 2 for state, etc
ActualLocation - Can be a city name if the locationType is 1 and so on..
RowId LocationType ActualLocation
1 1 Waltham
2 1 Yokohama
3 2 Delaware
4 2 Wyoming
5 3 US
6 3 Japan
the problem is I am only able to get the city name for all three fields using a join like this
select L.ActualLocation as CityName,
L.ActualLocation as StateName,
L.ActualLocation as CountryName
from UserTable U,
AllLocations L
WHERE
(L.ID = U.City and L.LocationType= 1)
AND
(L.ID = U.State and L.LocationType = 2)
What worked best for us was to have a country table (totally separate table, which can store other country related information, a state table (ditto), and then the city table with ID's to the other tables.
CREATE TABLE Country (CountryID int, Name varchar(50))
CERATE TABLE State (StateID int, CountryID int, Name varchar(50))
CREATE TABLE City (CityID int, StateID int, Name varchar(50))
This way you can enforce referential integrity using standard database functions and add additional information about each entity without having a bunch of blank columns or 'special' values.
You actually need to select from your location table three times - so you will still have the joins:
select L1.ActualLocation as CityName,
L2.ActualLocation as StateName,
L3.ActualLocation as CountryName
from UserTable U,
AllLocations L1,
AllLocations L2,
AllLocations L3
WHERE
(L1.ID = U.City and L1.LocationType= 1)
AND
(L2.ID = U.State and L2.LocationType = 2)
AND
(L3.ID = U.Country and L3.LocationType = 3)
HOWEVER
Depending what you want to do with this, you might want to think about the model... You probably want a separate table that would contain the location "Springfield Missouri" and "Springfield Illinois" - depending how "well" you want to manage this data, you would need to manage the states and countries as separate inter-related reference data (see, for example, ISO 3361 part 2). Most likely overkill for you though, and it might be easiest just to store the text of the location with the user - not "pure" modeling, but much simplified for simple needs... just pulling the "word" out into a separate table doesn't really give you much other than complex queries

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