travel distance table design - mysql

I have to develop a table that would contain distance between destinations and need some assistance for that. I am right now almost blank on how to start
here the table show distance from point A to A, B, C AND D ARE 0, 4, 8, AND 12 respectively and so on.
need to transform this data in MySQL table to be managed by admin panel and used at client site depending on from and to destination.
Regards

In case you don't have "real" date (like geolocation) you will need to store the data in 2 tables.
First table, locations (so store A,B,C,D there, and other relevant information about the location)
Second table, 3 columns. from_location, to_location, distance. (with a key on from/to_location so it is unique. But always check for the other way around before inserting, as you can support A,C and C,A in your table)
This way you can easily extract the correct data from the database.
For example, getting the distance from A to C (SELECT distance FROM distance_table WHERE from_location = "A" AND to_location = "C")

So basically you need a table that has 3 columns. Point A, Point B, distance
In your program, you can do 2 for loop to get through the 2 dimension table as inserts.
If you want it to be unique, then in your code, you make want to try if you currently looking at B to A, check if A to B already exist before inserting again. Might be wise to also place some constraint on the table where PointA and PointB Must be unique

Make a table
Create table `table_name`( `Distance_from` varchar(2), `A` int,`B` int, `C` int, `D` int ,primary key(Distance_from));
Then insert your record like
Insert into `table_name`(`Distance_from`,`A`,`B`,`C`,`D`) values('A',0,4,8,12)
similarly insert all your rows.

Related

INSERT ON DUPLICATE from another table

I have read a lot before asking but since I am a noob eith MYSQL the answers were a bit confusing to me so let me try to put my own question and see if someone can help.
I have a table called "parse" and this table has data I need to throw into another table called "updates".
Ok, so "updates" is created but now I have updated the data from parse (that is the source of the data) and both tables have a unique ID called "link".
I was planning to run "INSERT ON DUPLICATE" but not sure how to do it. So basically, the field "link" is the unique ID that needs to remain the same in both tables, but the rest will update like price for example in the table "updates".
Can you guide me on how to do this?
Thanks
The appropriate statement would have this form:
INSERT INTO destination (
-- List columns in `destination` here.
)
SELECT
-- List columns from `source` here. Ensure they correspond to the columns listed for `destination` exactly otherwise you'll get an error (or worse: unintentional data corruption).
FROM
source
ON DUPLICATE KEY UPDATE
-- List both `destination` and `source` columns again here, excluding immutable and key columns. Refer to the source column via `VALUES()`.
In your case, something like this:
INSERT INTO "updates" (
link, /* PK */
a,
b,
c,
d
)
SELECT
link,
a,
b,
c,
d
FROM
"parse"
ON DUPLICATE KEY UPDATE
a = VALUES(a),
b = VALUES(b),
c = VALUES(c),
d = VALUES(d);

Automatically calculate a database field from another table with a foreign key relation

I have 2 tables:
Table A with column A-id and double field column total amount,
Table B with foreign key column A-id and amount column.
I want the total amount in table A to change automatically, depending on the field.
Is this behavior possible to implement? Essentially, I'd like the field to hold a query that runs every time I add/delete/update a row in Table B. I'm using phpMyAdmin (if it's relevant).
I've tried using the following queries:
Take the current total amount and put them in a variable named i.
Make the changes in table B.
Update the new total amount in table A.
However, this hasn't been efficient.
Don't do that. Calculate the values on-the-fly in a single query. You need to join the tables for that
select *, a.amount + b.amount as total_amount
from tableA a
inner join tableB b on a.a_id = b.a_id
You can use trigger to do such a kind of things.
Otherwise you should make changes by using coding itself whenever B table got changes, it should affect A table. Whatever it may add, edit, delete.

mysql - add columns to a table or create new table and join

I have the following setup:
A table with n columns that contain let's say... pizza details. There are 4 kind of pizzas at this point
Until now all pizzas had same details, each detail saved in a column.
But now a new kind of pizza called super pizza appeared, that has 2 more types of details that needs to be saved.
There are 2 ways to do this (that I can think about):
Add to columns to the existing table, and leave them blank/null/whatever for the rest of 4 pizzas types
Create a new table with 3 columns (idPizza, newDetail1 and newDetail2), save pizza as the rest of pizzas, and when I get data join the 2 tables
First option has the disadvantage that I keep useless data for all pizzas except the new type (80% of the table at an average pizzas distribution).
Second option has the disadvantage that each time I get the new kind of pizza I need to make a join. Also the db will be kind of "messy"... having part of pizza element stored in a table and other part in another.
I know that ultimately is a matter of taste but how do you think I should proceed? I incline a bit to first option but a second opinion is welcomed.
As a note: There are lots of entries in the tables (like tens of thousands).
Second note (based on an answer): Can't refactor the "pizza" table, just add to it.
instead of this you can use flat table concept as follows whic hwill be easy for adding no of characteristic in future for new pizzas having some more details
CREATE TABLE pizza
(
id int auto_increment primary key,
name varchar(20),
details varchar(30)
);
INSERT INTO pizza
(name, details)
VALUES
('pizza1', 'nice pizaa'),
('pizza2', 'nice pizza#sqlfiddle');
CREATE TABLE details
(
id int auto_increment primary key,
name varchar(20)
);
INSERT INTO details
(name)
VALUES
('pizza_size'),
('price');
CREATE TABLE pizza_details
(
id int auto_increment primary key,
pizza_id int(10) ,
details_id int(10) ,
details_value varchar(20)
);
INSERT INTO pizza_details
(pizza_id,details_id,details_value)
VALUES
(1,1,'small'),
(1,2,'Rs 20'),
(1,1,'big'),
(1,2,'Rs 50');
and fire the query
select pizza.name as pizza_name,details.name as detail,pizza_details.details_value from pizza_details left join details ON pizza_details.details_id = details.id
left join pizza On pizza_details.pizza_id = pizza.id;
SQL Fiddle
I suggested for use first option. Because 2nd option reserve more resources than 1st option and it will take more time process.
As the disadvantages of 1st option you have mentioned is quite obvious,but when you need more column then add new to that existing table.
Well I suggest just create a table with attributes (idPizza, newDetail) and save data as below
idPizza, newDetail1
1 1 detail
2 2 detail
3 super detail
3 super detail second
MAke idPizza, newDetail1 as primary

Single FK referes to PK from multiple tables

I have Table A, Table B, and Table C. Table C has a column which should be a FK for a PK. The PK could be either Table A's id or Table B's id. What is the best practice to design such tables?
I am thinking of creating 2 columns in Table C, where the first one would determine either Table A or Table B, and the second one represents the id of either Table A or Table B (depending on the first column). Is it the right way to do it?
Using SQL UNION to Combine Two ResultSet with Different Joins
See: http://www.sqlfiddle.com/#!8/3519e/4
I have made an example with 3 tables:
CAR
TRUCK
DRIVER_ASSIGNED
You can create one query to join A with C, another to join B with C, and join the two result sets using UNION. For example:
(select * from `A`,
`C`
where `A`.ID = `C`.`ID` and
`C`.`Type` like 'A')
UNION
(select * from `B`,
`C`
where `B`.ID = `C`.`ID` and
`C`.`Type` like 'B')
In Relation to Classes and Sub-Classes
It seems to be that TABLE A and TABLE B are sub-types of another type/class. So, e.g. TABLE A may be cars, and TABLE B, may be trucks, but they extend vehicles.
In this case I think you need a fourth table, TABLE PARENT, that will combine the common fields of both A and B. C will use the primary key of TABLE PARENT as the foreign K.
TABLE A and B will contain both as foreign keys but maybe also as primary keys the primary key of table PARENT.
So, using my analogy with vehicles let us assume:
TABLE A = CARS
TABLE B = TRUCKS
TABLE C = ASSIGNED_DRIVERS
TABLE PARENT = VEHICLES
TABLE VEHICLES - PARENT of A and B
-------------
ID (PK)
HORSE POWER
LICENSE PLATE
etc...
TABLE CARS -
-------------
ID (PK)
VEHICLE_ID (FK linking to VEHICLES.ID)
NUMBER_SEATS
etc...
TABLE TRUCKS -
-------------
ID (PK)
VEHICLE_ID (FK linking to VEHICLES.ID)
HIGHT (meters)
MAXIMUM_STORAGE_WEIGHT
etc...
TABLE DRIVERS_ID -
-------------
VEHICLE_ID (FK linking to VEHICLES.ID)
DRIVER_OD
START_DATE
END_DATE
etc...
So, the following method would save you from this problem and also be more semantically correct.
You can also check online documentation such as:
http://www.dssbooks.com/web/Files/LookInside/Web-DSS-Chapter-03.pdf (page 55) to see the theory between classes and subclasses.
I am thinking of creating 2 columns in Table C, where the first one would determine either Table A or Table B, and the second one represents the id of either Table A or Table B (depending on the first column). Is it the right way to do it?
No. You would be preventing the DBMS from enforcing the foreign key. You'd have to enforce the FK through triggers or the application code, which is more prone to errors and potentially less performant.
Either make two FK fields (one for Table A, other for Table B) and use a CHECK1 to ensure only one of them is not NULL, or use inheritance.
More info in this post.
1 Unfortunately, MySQL parses but doesn't enforce CHECK constraints, so you'll need to use a trigger instead. This limitation doesn't exist in other DBMSes.

Copying certain data from one table's columns into another through a link table

As part of a very slow refactoring process of an inherited system, I need to eliminate a couple of slow joins and subqueries. As I'm familiarising myself with the system, I'm slowly sanitising the database structure, to get rid of the held-together-by-duct-tape feeling, making incremental improvements, hoping nothing breaks in the meantime. Part of this involves combining data from two tables linked by a third into one.
Table structure is similar to this:
CREATE TABLE groups
(
group_id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
-- various other fields that are appropriate to groups
...
-- these fields need to be filled
a ENUM(...) NOT NULL,
b INTEGER NOT NULL,
c VARCHAR(...) NOT NULL
);
CREATE TABLE items
(
-- key is determined by an external data source
item_id INTEGER NOT NULL PRIMARY KEY,
-- various other fields that are appropriate to items
...
-- these fields shouldn't be here, but in the groups table
a ENUM(...) NOT NULL,
b INTEGER NOT NULL,
c VARCHAR(...) NOT NULL
);
CREATE TABLE group_items
(
item_id INTEGER NOT NULL,
group_id INTEGER NOT NULL,
PRIMARY KEY (item_id,group_id)
);
An item may be in more than one group. Each record in the table "items" has values for columns a, b and c, which are actually not properties of the items, but of the groups of which the items are a part. (This is causing problems, as the values may be different if the item is in another group).
I can't remove the fields from the items table yet, as they are filled by an insane import process from an almost-as-insane data source. Until I get around to fixing the import process, I'm stuck with having the fields exist in the items table, but in the short term at least I can eliminate the slow lookups to get them.
Right now I have a loop in PHP that runs over each group, takes the values from the first item it encounters (which is fine -- all items in a group will have the same values for a, b and c) and places them into the group. This process is rather slow and laborious and unfortunately runs very frequently on an overloaded and underpowered server. Is there a smart way to copy these (and only these) values from the items table into the groups table and have MySQL do the heavy lifting, rather than relying on a PHP script?
Looks like I found my own answer. As the number of items in each group is relatively small, there may be some duplicate work being done but it's not a bottleneck and much faster than the PHP loop:
UPDATE
groups g
INNER JOIN group_items USING(group_id)
INNER JOIN items i USING(item_id)
SET
g.a = i.a,
g.b = i.b,
g.c = i.c;
Seems to do what I need.