In database conception, could I make a join between three tables ? Like this:
Edit:
I am asking on design, and not code !
this database design is possible and valid. But it is extremely hard to say yes or no, because every database design heavily depends on the requirements. As I can see from the image, you have done something similar to this:
The red rectangle represents FOREIGN KEYS. If you look at my image, you will see, that the MainTable table has only 3 fields and those 3 fields are foreign keys. This is possible, but when we design, we usually add other fields (not related to other tables) to the table. For example, lets say that:
Table1 ==> Car
Table2 ==> Driver
Table3 ==> City
MainTable ==> DriverWhoDrivesACarInACity (ridiculous name but you get the point)
With image in mind, you see that in the MainTable, we are actually storing information about which Driver drove a certain Car in which City (dont pay attention to the real life meaning of this, because it is not relevant at this point). Everything looks good. You start your application and you start inserting data. And then some day it happens, that a certain Driver wants to drive a certain Car in a certain City that he already drove in. That means you will have a duplicate row in the table MainTable. And at this point, you see that there could be some problems with this design. And after some thought, you decide to add another field to your MainTable table: you add "Date and time of usage" so that you know when the car was driven.
So now you have something like this:
Please note that you dont "need" foreign key relationships, it is just a good practice in order to sustain database integrity!
Here is a sample for SQL server...try accordingly.
SELECT p.Name, v.Name
FROM Production.Product p
JOIN Purchasing.ProductVendor pv ON p.ProductID = pv.ProductID
JOIN Purchasing.Vendor v ON pv.BusinessEntityID = v.BusinessEntityID
WHERE ProductSubcategoryID = 15
ORDER BY v.Name;
select f1.*,f2.*,f3.* from f1 a
join f2 b on a.1=b.1
join f3 c on a.1=c.1
Related
I have to tables. A table that we call "The Vault" which has a ton of demographic data and Table A which has some of the demographic data. I am new at SQL Server, and I was tasked with finding a list of 21 students in The Vault table (Table B). Problem, there is no primary key or anything distinctive besides, FirstName, LastName, BirthMonth, Birthday, Birthyear.
Goal: We could not match these people in the conventional way we have, and so we are attempting a Hail Mary to try to see which of these shared combinations will perhaps land us with a match.
What I have tried doing: I have placed both tables on tempt tables, table A and table B, and I am trying to do an Inner Join but then I realized that in order to make it work, I would have to do a crazy join statement where I say (see the code below)
But the problem as you can imagine is it brings a lot more than my current 21 records and is in the thousands so then I would have to make that join statement longer but I am not sure this is the right way to do this. I believe that is where the WHERE clause would come in no?
Question: How do I compare these two tables for possible matches using a WHERE clause where I can mix and match different columns without having to filter the data constrains in the ON clause of the JOIN. I don't want to JOIN on like 6 different columns. Is there another way to do this so I can perhaps learn. I understand this is easier when you have a primary key shared and that would be the JOIN criteria I would use, but when we are comparing two tables to find possible matches, I have never done that.
FROM #Table a
INNER JOIN #table b ON (a.LAST_NAME = B.LAST_NAME AND a.FIRST_NAME = b.FIRST_NAME.....)```
I have 4 tables, 3 tables that refers to area, station and trainer. The last one merges the ID from the first 3 tables in order to make the structure easier.
I would like a query that shows only a determined area with the respective operations and trainers based on the idArea, something like this:
The answer to the actual question you asked is "natural join".
If you do the natural join between these 4 tables/relations you have, you get a 6-column table/relation : 3 id's and 3 names.
If you project away the 3 id's from that (in SQL, SELECT NAMEAREA, NAMESTATION, NAMETRAINER from that), you get the table/relation you said you were after.
In SQL, doing the natural join can be done using the NATURAL JOIN keyword, or it can be done spelling out the equijin conditions explicitly using ON :
SELECT NAMEAREA, NAMESTATION, NAMETRAINER FROM
REGISTERS NATURAL JOIN AREA NATURAL JOIN STATION NATURAL JOIN TRAINERS
or
SELECT NAMEAREA, NAMESTATION, NAMETRAINER FROM
REGISTERS JOIN AREA ON REGISTERS.IDAREA = AREA.IDAREA
JOIN STATION ON REGISTERS.IDSTATION = STATION.IDSTATION
JOIN TRAINERS ON REGISTERS.IDTRAINER = TRAINERS.IDTRAINER
(Didn't spell-check this on any engine, so perhaps beware of syntax mistakes on my part - still you should be able to advance.)
(Note that in this latter case, the JOINs per se, i.e. without the SELECT, do not yield a 6-column table, but a 9-column one : each id twice, plus the corresponding names. Meaning the JOINs per se here do not constitute a natural join strictly speaking, but that is irrelevant for the practical purposes you are pursuing. Just a tiny bit of education about fundamentals worth remembering.)
Problem
How can I display the area and station name from two tables?
In a Relational database (noting the tag), that is simple.
How can I display the area and station name from two tables based in a third table with ID only?
The simple answer is, with id on every file, you can't.
The explanation is as follows.
The Relational Model is logical.
Record IDs are physical, anti-relational, 1960's Record Filing Systems. It is what we had before DBMS, and before the advent of the Relational Model in 1970. They have none of the Relational Integrity; Relational Power; or Relational Speed of a Relational database.
Whatever you have read re placing a Record ID in a file, is pig poop.
Eg. You have this problem right here, that Relational databases do not have.
Beware, such primitive RFS are heavily promoted and marketed as "relational", by the "theoreticians".
Stamping a Record ID on every file (they are files right now, not Relational tables) cripples the data modelling exercise, as evidenced here, in your question (and a hundred other questions I have answered).
Clarification Requested
In a Relational database, what you are seeking is simple. Correcting your files and elevating them to Relational tables, is easy enough. But first we need some clarifications:
Don't worry about the Registers file right now. At best, it is unresolved, and it will change drastically when Area; Station; and Trainer are clarified.
It appears a Station belongs to an Area. Fine.
Then a Trainer belongs to a Station, as well as to an Area:
that is not logical
either a Station (and thence to an Area because a Station belongs to an Area)
xor an Area, would be fine. But not both
that would be a simple hierarchic structure.
If a Trainer indeed belongs to both an Area and a Station, ie. It is not a hierarchic structure, then you need to declare the conditions. Such as, there are Area-Trainers and Station-Trainers, and the conditions for such.
Please clarify, so that the question can be answered.
Comments
Cézar, you can skip this section.
AntC:
"Stamping a Record ID on every file ..." I see no RecordIDs on any table.
Note that in the question, we notice an id on every file. That is a Record ID. It can be a INT, BIGINT, NUMERIC(1), GUID, etc. It might be named id, Id, ID, iD, etc. It is manufactured by the system. It is not from the data. It is properly called a Record ID because it is a physical pointer to a record, not an Identifier to a logical row.
That is the hallmark of a 1960's Record Filing System. What we had before DBMS, and before the Relational Model. That is what is heavily promoted and marketed by the "theoreticians" as "relational".
The Relational Model is Logical. Keys must be "made up from the data". Surrogates such as Record IDs (regardless of what it is named) are specifically prohibited.
This question seeks a Relational database. Not a primitive filing system.
I see ids for business-oriented entities.
That is not possible. The question asker has not developed the files yet. There are no "business-oriented entities" in the question. Only four simple files with physical Record IDs named id.
In any case, if and when we progress to "business-oriented entities", ids are 100% redundant, one additional column and one additional index on every table.
I'm kinda new in databases and I need to solve this one:
client(NAME, CITY, STREET, NUMBER, BALANCE, CLIENT_CODE);
order(ORDER_NUMBER, CLIENT_CODE, PROVIDER_NAME, FUEL, QTY, DATE);
provider(PROVIDER_NAME, PROVIDER_ADRESS, FUEL_CODE, PRICE, STOCK);
fuel(FUEL_CODE, FUEL_NAME);
I've already tried (and succeeded I guess) to create an ALTER TABLE for provider and fuel named provider_fuel in order to solve many-to-many relationship, but I don't have any idea how I could create a connection between order and provider.
I've changed the entities like this:
provider(PROVIDER_ID, PROVIDER_ADRESS);
fuel(FUEL_CODE, FUEL_NAME);
provider_fuel(ID_ENTRY, ID_PROVIDER, ID_FUEL, PRICE, STOCK).
Is that even ok? If so, how can I make connections between all those entities in my database?
I have to mention that my app should allow clients to place orders from providers who have their specific fuels, prices and so on.
I would suggest the following table layouts:
address(ID_ADDRESS, CITY, STREET, NUMBER);
client(ID_CLIENT, NAME, ID_ADDRESS);
client_order(ID_CLIENT_ORDER, ID_CLIENT, RECEIVED_DATE);
client_order_detail(ID_CLIENT_ORDER_DETAIL, ID_CLIENT_ORDER, ID_PROVIDER, ID_PRODUCT,
ORDER_QTY, STATUS, DELIVERED_DATE); -- Status in ('OPEN', 'DELIVERED')
provider(ID_PROVIDER, NAME, ID_ADDRESS);
product(ID_PRODUCT, PRODUCT_NAME);
provider_product(ID_PROVIDER, ID_PRODUCT, PRICE, STOCK_QTY);
You can, if you like, expand this. For example, a provider might have multiple locations from which product can be supplied, in which case you'd need to re-work the single PROVIDER table into something like
PROVIDER(ID_PROVIDER, NAME)
PROVIDER_PRODUCT(ID_PROVIDER, ID_PRODUCT, PRICE)
PROVIDER_ADDRESS(ID_PROVIDER_ADDRESS, ID_PROVIDER, ID_ADDRESS)
and then rework PROVIDER_PRODUCT as
PROVIDER_ADDRESS_PRODUCT(ID_PROVIDER_ADDRESS, ID_PRODUCT, STOCK_QTY)
I suppose it's also possible that the price a provider charges might depend on the location from which it's shipped so you might need to change the model to accommodate that. The point is that there are many different ways to do this, and it depends very much on the requirements you have.
EDIT
To obtain the total value of an order using the tables above you'd use a query such as:
SELECT co.ID_CLIENT_ORDER, SUM(cod.ORDER_QTY * pp.PRICE) AS ORDER_TOTAL_VALUE
FROM CLIENT_ORDER co
INNER JOIN CLIENT_ORDER_DETAIL cod
ON cod.ID_CLIENT_ORDER = co.ID_CLIENT_ORDER
INNER JOIN PROVIDER_PRODUCT pp
ON pp.ID_PROVIDER = cod.ID_PROVIDER AND
pp.ID_PRODUCT = cod.ID_PRODUCT
GROUP BY co.ID_CLIENT_ORDER
ORDER BY co.ID_CLIENT_ORDER
You can put id_provider in order table and get the provider details by the id .For ex
Select *,p.price,p.fuel_code from order as o join provider as p on o.id_provider=p.id
Welcome to the Oracle database world!
You can make connections between tables or views using JOIN structure.
In your example, you can connect your tables like this:
SELECT od.* FROM order od, provider pd WHERE od.provider_name=pd.provider_name
Or you can write it like this. It's up to your style. But I prefer the first one.
SELECT od.* FROM order od INNER JOIN provider pd ON od.provider_name=pd.provider_name
But it's always better using NUMBER type columns in joins. So I suggest, create provider_id (NUMBER type) on 2 tables and join them.
There are 5 main types (INNER, OUTER, FULL, LEFT, RIGHT) of joins in SQL. Each of them provides different things.
If I understand correctly your database represents a market place where a client can buy different kinds of fuels from providers. So far you have used natural keys:
A client has some login code that identifys them (client_code).
A provider is identified by their name. Do you want this? That would mean a provider address stays constant and cannot change. That may or may not be desired. If the company JACOB'S FUELSHOP INC changes to THE FUELSHOP INC, do you want to treat it as the same company or a different one?
You also generate order numbers. Do you want them unique in your database, or per client or per provider? The order table's key would accordingly be either just order_number or order_number + client_code or order_number + provider_name.
Now you don't want to have one provider only sell one type of fuel, but various types. You introduce a bridge table. But in the same step you introduce technical IDs. Do you want to use technical IDs instead of natural keys?
You have provider(PROVIDER_ID, PROVIDER_ADRESS) where the provider's name is either missing or included in the address. This allows you to change the name later. But remember that you may want to store the name then with every order, as you may want to reprint it later or just say whether you placed the order with the legal company JACOB'S FUELSHOP INC or THE FUELSHOP INC. Technical IDs are fine, but you must remember to still keep unique constraints on the natural keys and think about consequences as the one just mentioned.
As to the fuel price: You are storing the current fuel price, but you are not storing the price when ordered. Add the price to the orders table.
As to your question: Order and provider are already linked by provider_name in the original design. In the new design you've introduced the provider_id. If you want to use this instead, put provider_id in the orders table. As mentioned, you may or may not want the provider name in that table, too.
I need to connect id_player from table Players to player_score and player_assist in table Goals. The primary key must refere to these two.
Is there any way how to do it?
Access writes me "The relationship already exist".
I will be grateful for every answer.
Access screen - Access
Is this the correct solution? - Possible solution
For each Foreign Key reference existing in a table; a separate join must be made to the main/base table to get the related data.
In your case; add Players again to your query and join it to the Goals.player_assist; while joining Players to Goals.Player_Score.
As to why: The same join can't get both pieces of data as they represent different relationships to the players table.
in SQL this would look like:
SELECT G.*
, PS.id_Player as ScoredByID_Player
, PS.first_name as ScoredByfName
, PS.last_name as ScoredBylName
, PA.id_Player as AssistedByID_Player
, PA.First_name as AssistedByfName
, PA.Last_name as AssistedBylName
FROM GOALS G
INNER JOIN Players PS
on G.id_Player = PS.Player_Score
LEFT JOIN Players PA
on G.id_Player = PA.Player_Assist
Note we alias the field names from players so we know which is scored by and which is assisted by. We also alias the tables for readability and because we have to copies of "Players" and for the engine to keep track of which table we mean; we have to have them "named" differently.
The reason why I LEFT join (outer) the second time, is because not all scores have an assist; but all scores have someone scoring them. So the first join to players can be an inner join but the second join may not have an assist; and we still may want to see details for all goals made. If we made the 2nd join an inner one, we would lose all scores where an assist wasn't involved.
This should be a simple Yes/No answer so here goes.
If I set a 3 tables, 2 typical recordsets and 1 that joins them by the id of the 2 tables, do I need the id from both tables in order to have an entry in the join table?
The scenario is a Jobs table and a Parts table linked by JobsParts table. But some parts are not in the Parts table, they are just freetext entries (so as to avoid stock control issues) belonging to a Job.
Hope this is enough to explain my question.
Thanks
BTW using CakePHP 2.0
For database sanity, I'd say the join table 'jobs_parts' should have both IDs.
If you try entering free-form parts into the join table, you're not only going to increase the size of the join table, but you've effectively lost the ability to grow/expand - ie. what if you want to add a few more fields to this unknown part? Or what if it turns out to be a part that you actually want in your normal parts table.... it just gets confusing.
There are other options for dealing with free-form parts vs actual parts...
have a field in the parts table that's a tinyint(1) for whether or not it's a verified part
OR make an UnknownParts model/table
In my opinion, go with what makes logical sense for ease of understanding and for future updates to your database/website...etc. And IMO, adding a freeform part into the join table would not fit that bill.