How to move SQL info from one DB to another - mysql

Im trying to migrate SQL From one script to another, Namely only one part of it, but they use different "Code".
Basically im trying to move information for "States" which is held as a number in side both DB's. But the numbers of course are different, For instance Arizona's in one is 12 but the other is 3425.
Im trying to find a way to First match the Customer ID which is the same in both, then grab the Number from one DB and then convert it to the number it is in the new DB and place it in the correct area in said DB.
But my skills with SQL are very lacking and i can't find a reasonable solution.
Scripts in use:
Old - CRE Loaded 4.2.1a
New - OpenCart (Current Version)
EDIT
Here is my best at explaining the DB structure, excuse me if its not the best explanation of how the DB works:
Here is the Old DB Structure for the Tables that are involved:
address_book - Holds customer Information, State number is held in the Colum entry_zone_id in number format, also the Country number is held in entry_country_id also in number format, the "Zone ID" is based off of the "Country ID" depending on the country.
zones - Holds State and Country ID Information, the Example:
for arizona the zone_id is 4, the zone_country_id is 223 (For USA), the zone_code is AZ, and the Zone_name is Arizona
customers - This holds the main customer information, not includeing address info, customers_id is of course the customers ID Number which corrosponds with the same Customer ID in the table address_book. customers_default_address_id also corrosponds with the ID in address_book.
Now as for the new DB:
oc_address - address_id and customer_id mark the customers ID number. country_id tells which country they are in, Its in number format. zone_id holds the state's DB number.
oc_zone - "zone_id" holds the Zones ID, "country_id" holds the countrys ID number, such as USA is. "name" is the state name. "code" state or country code. Example:
Arizona in the DB shows like this:
zone_id=3616, country_id=223, name=Arizona, code=AZ, status=1(shows that its used)
One that may also be needed to know is this one:
oc_country - holds country info, country_id holds country code, name is the name of the country, isa_code_2 and iso_code_3 are the country ISO codes.
i hope this is of use.

Related

Database design without a 1 column table

I have been working on a database design and I'm stuck hitting a wall. I'm ending up with what I'm reading is not a normalized database structure but I'm having issues trying to find a "more correct" design and if this design is acceptable how do I execute it in Access?
TLDR: If a table with a single column set as an auto number is an acceptable design, how do you go about inserting a record in it using Access?
The segment of the database of concern is creating a structure for storing companies. Requirements for this is that any changes need to be approved by another user and all historical changes need to be captured so that it can be easily reverted also a company can have multiple aliases but only one legal name.
There is three tables in my solution but one of them is a single column table. From what I've read 95% of people on stack overflow all think its a very bad idea but I've found one post were people are that there are cases for it. I think this is not normal also because I can't find a way to just create a new record in a table with only an auto number column (In Access I have not tried others yet).
Table Structure
Company Names : ID, Company ID, Is Legal Name, Created By, Created On, Approved On, Approved By, Event ID, Is Active
(A company could have a few different names known to the public: TD vs Toronto Dominion. Each name is inserted here with a reference to the company it belongs to)
Companies : ID (Auto Number)
(A company exists and this is its ID)
Companies History : ID, Company ID, Market ID, Holding Company ID, Created By, Created On, Approved On, Approved By, Event ID, Is Active
(These are the historical changes that have been made to the company and who did them and who approved them)
Column Notes:
Event ID : is a FK reference to a table holding each record of actions that have either created, updated or deleted records. (User Research using method [y], Typo Fix, ...)
Is Active : Since deleting records is not possible (historical records need to be kept) this column is used to track if this record is to be included in queries.
Options I see and their issues:
I could get rid of the companies table and make Companies History : ID be the new company id but I find that in that case each time I want to update a company I would need to update each FK reference to the previous company id (I don't think this would be a very normalized approach)
Another Option I see is that I get rid of Companies table and use Company Names : ID as the company id and I would add a column to Company Names called Alias of Company ID. I find that solution adds a log of complexity to my stored data where an alias has company information that differs from the entry that was aliased.
Another Option is that I could add the columns: Created By, Created On, Approved On, Approved By, Event ID and Is Active but this would be duplicating information found in the first record for this company in the Companies History table and this isn't adding any real description to this record.
Anther Option is that I make the Companies table a mirror of Companies History and that when I update or insert a record in Companies I would also insert a record Companies History. With this solution I find that again I duplicate information, that newest record in "Companies History" would hold the same information found in last Inserted or Updated record in in Companies
Another option but is to replace the Companies : ID auto number with a short text and I just get the hash of the current timestamp + a random int. I can now insert new records into this table using access but I feel that this is overkill since I just need the exact same functionality as the auto number.
Another option is move only the legal name into Companies table but now when the legal name of a company changes I have no way of tracking this. Also if I want a list of all names I need to use a union on Companies and Company Names. I find that using unions can reduce performances of queries and I use them only when explicitly needed.
If I don't want to duplicate any information and I don't want to update all FK it seems that I need a table with a single column. If this is acceptable how do I go about inserting a record into a table with a single column set to auto number in Access.
If Companies can be derived from CompanyNames (select distinct CompanyId from CompanyNames), there is no point storing again that information. Just replace that table by a view if you want it (but it as little added value).
On the other hand, if CreatedOn refers to the Company creation (not the row creation) then it is obviously a property of the Company, and I would rather work with
Companies --> Aliases.
But of course I don't know the ins and outs of the reality you're dealing with.

SQL (MySQLi) best fit for text comparation

i have the following scenario:
DB table of addresses linked with region ID. Based on address, the workers sorting the packets (QR scanning) to the shelves and re-distributing them to the warehouses all around the capitol city. So far so good, everything seems OK, but there is a problem:
My DB table (MySQL) has the following fields:
ID (*auto increment, PK)*
STREET_NAT (*local name of the street - Cyrillic*) UTF8
STREET_EN (*English name of the street - Latin*) UTF8
REGION_ID (*number from 1 to 116 , that describes in what part of the town (warehouse) will be the package distributed*)
The problem is, sometimes the addresses are not correctly written plus as a bonus, sometimes they are in Cyrillic, sometimes in Latin.
I need to create a sorting system that analyzes the best fit of the street address and decides in which part of the city will travel the package. But the people makes mistakes (for example they are not entering "Jules Verne str." , but "Jul Vern st." , or even in Cyrillic with mistakes.
So my question: Does exists some procedure/method in MySQL to guess the best fit for the address? I am thinking in point system based on
php:
$query = "
SELECT REGION_ID FROM ADDRESSES WHERE STREET_NAT LIKE '%{$scanned_address}%'
OR STREET_EN LIKE '%{$scanned_address}%' "
this system works in approx 55% of the cases,when the sender of the package does not makes a mistake. I need to improve this select to add something like "Points" how close is the scanned address to the database field value. Best fit wins, and the region ID will be shown and sorted to the corresponding shelve. I am talking about thousands of packets / day.
Any ideas?
Thanks
i have an idea, create a table with the street correct names in it, in Israel we have this data for free, then you can compare from what the user types to the data in your database table with the correct street names. so it's auto complete.
you don't need to insert the values your self. just find a data source that can provide you this data, and it will be autocomplete for the user.

Database design structure

I´m new to database design and never took class on it, i have problem with structuring my database and assigning primary keys.
I have a list of cities, each city has 5 types of public transport. Each type of public transport has different ticket price, main station and CSV file with route coordinations etc. in every city. Then i need to daily calculate average cost of transportation in every city for each type of public transport based on route coordinations (distances), price, time it takes etc.
Table cities:
city (Primary key)
Table public transport:
city, type of transport, ticket price, main station, file1, file2
Table results:
city, type of transport, date, cost
How should i connect these tables (assuming their structure is right)? In table public transport, i think city should be foreign key but type of transport will repeat for every city so i dont think it can be primary key of this table - the same for table results.
The main idea is that you don't wish to repeat ya self. Not only is it an overhead but also it's quite error prone when you wish to change multiple entries that represent the same thing.
There are guidelines on database normalization which help you to ensure that your data is on a form that's easy to maintain and work with.
You don't need to become an expert in understanding which form does what, but being able to identify what should be kept separated is a must when it comes to database designing.
You should list what you know:
Different cities.
Different type of transport.
Different ticket prices.
Different stations.
If you create a separate table for all of those then it'll be easy to link them together in rows in a table that then represents something on a larger scale. Every entry should have a separate id that will be your primary key, you need to be able to allow e.g. multiple cities with the same name, thus not being able to hold a unique value if they are to be the primary key.
E.g. now it would be easy to identify routes for a city, there can be multiple routes in a city
route_id | city_id | route_name
1 2 test1
2 2 test2
You then could add another table that represent which kind of transport is tied with this specific kind of route.
route_id | transport_id
1 3
2 4
You're then able to create a new table that holds points of stations that are a part of your route and you can even identify whether it's a main route or not.
route_connected_id | route_id | station_id | main_route
1 1 2 1 // a main route
2 1 3 0 // not a main route
And it goes on and on, separating the most simple entries allows you to create complex relationships where all you have to do is link ids.
This is the basic idea which should hopefully get you started, whether you find it helpful or not then I recommend that you take a look on the reading material that I suggested, i.e. database normalization.

People has 3 Addresses and Address belongs to People, what's the best practice?

In mysql database with cakephp 2.4.3.
People always have 3 addresses.
registed address.
Where they live now.
Where they work.
Both tables are just like people timeline.(Mean the record increase overtime)
for example, if you change your name in real life. you will have to add new record in people table.
something like this for 1 person.
Year name address address2 address3
2013 Parker boon 13/3 huston,usa null 332/2 tansania
2014 Parker samel 13/3 huston,usa 23,NY,usa 332/2 tansania
2015 Parker samel 13/3 huston,usa 23,NY,usa 992 osky,russia
in 2013 parker boon lived at his regised address.
in 2014 he moved to 23,NY,usa.
in 2015 he works in russia.
I have 2 questions.
first, I made 3 foreign keys in People table(address_id,address2_id,address3_id)
and dedicated 3 Address id for just 1 people.
in People table.
people_id(PK),
name ,
address_id(FK),
address2_id(FK),
address3_id(FK)
in Address table.
address_id(PK) ,
address_name
Is it better than made 1 foreign key in Address table (people_id) ?
in People table.
people_id(PK) ,
name
in Address table.
address_id(PK) ,
address_name,
people_id(FK) ,
address_type,
(registed,lived,work)
second, whether my method is bad or not. I want to know how to config model and
saveAssociated() or save with transaction in cakephp for learning.
link to cake saveassociated
I think, the relation should be as follow:-
User has one addesss.
An address belongs to user.
In address there should be fields as:-
year, user_id, name, address1, address2, address3 and is_active
if any address would be change you need to generate the new record with clone of last record and updated one with status active and deactive the previous record.
take an example.
if the user modified the address2 only---------
You'll copy the address1, and address3 from the last record and set the status as active for new record that you're going to insert.
Deactivate the last record.
Conclusion:-
At the one time only one record would be active so you can handle association with hasOne.
You'll able to manage the history of history change.
There are a number of ways to do this, and the best would depend on your specific requirements for your app - we don't know enough now to say for sure.
But from what I can see, it sounds like you basically want to keep track of:
a) A person
b) A person's work address
c) A person's home address
d) changes to either a person's name, or a person's home or work address.
It sounds like the "registered address" is just their most recent previous home address.
I definitely would NOT be creating a new record in the people table when a person changes their name - they're not a new person; they're the same person with a different name. Likewise, with addresses, you don't necessarily want to create a new record when someone's address changes (you might - depends on your requirements).
One really simple way would be to have a people table, and a people_histories table.
The people table would store both the persons name, and the persons work and home address. And the people_histories table would just keep track of changes to any fields in your people table. A 'person' would have many 'person_histories', and each 'person_history' record would indicate the field that was changed, the date it was changes, and what value it previously held.
Another way would be to have people, people_histories, addresses, and address_histories, and a person has a work_address_id and a home_address_id.
Yet another way would be to say a person has_many addresses, and each address as a role, either 'work' or 'home', and a date indicating when the person moved to that address. A person may end up with eg. 10 work addresses, and you know that the current one is the most recently dated one.
Really, though, the best solution depends on what you want to do with people's previous names and addresses. If you just want to keep track of them for manual viewing, and they're not really a central part of the system, then a histories table keeps things simple, and works well.
Oh, and another thing, you should stick to CakePHP conventions, and name your primary key fields simply 'id'. And if you've got more than one foriegn key pointing to the same table, rather than naming them address1_id and address2_id, I'd name them descriptively, like home_address_id, and work_address_id.

Database Normalization with user input

I develop a mysql database that will contain the country,city and occupation of each user.
While I can use a "country" table and then insert the id of the country into the user table, I still have to look for the perfect method for the other two tables.
The problem is that the city and occupation of each user are taken from an input field, meaning that users can type "NYC" or "New York" or "New York City" and millions of other combinations for each town, for example.
Is it a good idea to disregard this issue, create an own "town" table containing all the towns inserted by users and then put the id of the town entry into the user table or would it be more appropriate to use a VARCHAR column "town" in the user table and not normalize the database concerning this relation?
I want to display the data from the three tables on user profile pages.
I am concerned about normalization because I don't want to have too much redundant data in my database because it consumes a lot of space and the queries will be slower if I use a varchar index instead of an integer index for example (as far as I know):
Thanks
We had this problem. Our solution was to collect the various synonyms and typo-containing versions that people use and explicitly map them to a known canonical city name. This allowed to correctly guess the name from user input in 99% of cases.
For the remaining 1%, we created a new city entry and marked it as a non-canonical. Periodically we looked through non-canonical entries. For recognizable known cities, we remapped the non-canonical entry to the canonical (updating FKs of linked records and adding a synonym). For a genuinely new city name we didn't know about we kept the created entry as canonical.
So we had something like this:
table city(
id integer primary key,
name varchar not null, -- the canonical name
...
);
table city_synonym(
name varchar primary key, -- we want unique index
city_id integer foreign key references(city.id)
);
Usually data normalization helps you to work with data and keep it simple. If normalized schema not fit your needs you can use denormalized data as well. So it depends on queries you want to use.
There is no good solution to group cities without creating separate table where you will keep all names for each city within single id. So it will be good to have 3 tables then: user(user_id, city_id), city (city_id, correct name), city_alias(alias_id, city_id, name).
It would be better to store the data in a normalized design, containing the actual, government recognized city names.
#Varela's suggestion of an 'alias' for the city would probably work well in this situation. But you have to return a message along the lines of "You typed in 'Now Yerk'. Did you perhaps mean 'New York'?". Actually, you want to get these kinds of corrections regardless...
Of course, what you should probably actually store isn't the city, but the postal/zip code. Table design is along these lines:
State:
Id State
============
AL Alabama
NY New York
City:
Id State_Id City
========================
1 NY New York
2 NY Buffalo
Zip_Code:
Id Code City_Id
=========================
1 00001-0001 1
And then store a reference to Zip_Code.Id whenever you have an address. You want to know exactly which zip code a user has (claimed) to be a part of. Reasons include:
Taxes for retail (regardless of how Amazon plays out).
Addresses for delivery (There is a Bellevue in both Washington and New York, for example. Zip codes are different).
Social mapping. If you store it as 'user input' cities, you will not be able to (easily) analyze the data to find out things like which users live near each other, much less in the same city.
There are a number of other things that can be done about address verification, including geo-location, but this is a basic design that should help you in most of your needs (and prevent most of the possible 'invalid' anomalies).