There is probably a simple solution to this but I'm stumped.
I have a master table with one ID field. There is a child table with that ID in two possible fields. Think of a doubles team with Player A and Player B. The Master table will have two records, one for each player. The Child will have one record with the Player A ID in one field and the Player B ID in a second field.
When I use the Master/Child and I'm sitting on Player A I will only see the child records if Player A is in the first ID field. If I move to Player B then I see nothing in the child table if Player B ID is in the second field.
Any help?
Thanks,
Don
Gday,
If I read you aright, you want to return each child row that has the parent ID in either A or B.
To do this in a query, you could write:
select A, field1, field2...
from
childtable
where
A = :keyvalue
union all
select B, field1, field2...
from
childtable
where
B = :keyvalue
Hope it helps!
The Child will have one record with the Player A ID in one field and the Player B ID in a second field.
In that case, you should consider using an fkInternalCalc field on the Detail table (if your TDataSet type supports fkInternalCalc fields, and deriving its value in the Detail's OnCalcFields event however suits your data model) and use that as the Detail field in an Index on the Detail table for selecting records which match the master. But generally speaking, needing to do that (i.e, link the Detail records on values from different fields) is a sign of imperfect data-modelling** - you might do better to have an intermediate "linking" table between the two tables you currently have,e.g. linking the Detail records to the Master on the basis of PlayerID, regardless of whether the player is "PlayerA" or "PlayerB".
** - the reason being that, as you have obviously gathered, the Master could be linked to the Detail on the basis of two different fields in the Detail table, and that does not fit with how M-D relationships traditionally work in Delphi (i.e. a single field or combination of fields with no alternatives) and in fact an extra, "linking" table is the better way to model the situation where the link needs to be defined on the basis of the values in Detail fields IDFieldA and IDFieldB.
Btw, what TDataSet descendant types are you using?
The simpler and much faster running answer to the UNION ALL join is
SELECT Mast.* ,DetA.* ,DetB.* FROM
MAST
JOIN Det AS DetA ON Mast.AID=DetA.Det_ID
JOIN Det AS DetB ON Mast.BID=DetB.Det_ID
If you want to be able to have any number of players in the game, then each Det record (player) needs to point to the master using the Mast_ID. You can do a similar join that way, but you will get one record per player if you do. The way I did it above gives you one record for each master/detail A/Detail B combination.
Related
This is complicated and difficult to explain, but here it goes. I have created a db that works just fine. It is a time saver, but not efficient for the user. I have a form for the merchandise where the user selects a paper type from a combobox. They are presented with two choices. They must also select a print size from another combobox. They are presented with 5 choices. I have VBA code that creates a SKU number based on these selections.
An art piece can use both paper types and be available in all 5 sizes. What I am trying to figure out is how I can offer all the possible choices on this form, allow the user to select options for that piece. As an example, the user chooses both paper types and all print sizes. This would create 10 SKU numbers for one art piece. Below is a copy of the form in it's current view:
Is this possible to do from one form? If so, how can this be accomplished in the most efficient way? I feel that it can. In VBA, this would be an IF nest nightmare, especially when concatenating the SKU variables. Either Select statements or another method that I am unaware of, could be the solution.
Thanks in advance for any and all suggestions and assistance.
EDIT: I hope this helps clarify. I would prefer to use this form
to complete the task. The checkboxes are not in an option group so they could all be checked if the user requires it. For the purposes of this question, let's assume the user has checked all the boxes. This would equal 10 total combinations.
I run this sub to generate a SKU based on the paper type and the print size:
Private Function UpdateArtwork()
Me.MerchandiseSKU = Me.cboArtworkID_A5A.Column(5) & _
Me.cboPrintTypeID_A5A.Column(2) & Me.cboPaperTypeID_A5A.Column(0) & _
Format(Me.cboPrintSizeID_A5A.Column(0), "00")
Call UpdateArtworkPic
End Function
I am trying to figure out how to write the code for the new form that allows all 10 SKU numbers to be generated and create 10 new records for Artwork_ID (Artwork table).
I think that the best way of doing this would be to create a new table, called tblArtworkSKU, which has the following fields:
ArtworkSKU_ID - Autonumber, primary key;
Artwork_ID - number, foreign key from the Artwork table;
PrintSize_ID - foreign key from the PrintSize table;
PrintType_ID - foreign key from the PrintType table;
ArtworkSKU - text.
You would then create a small continuous form based on this table, with PrintSize_ID and PrintType_ID selected through combo boxes. When you place this form onto the main form that you have, Access should automatically let you join on Artwork_ID to create a one-to-many relationship.
You could then use the AfterUpdate events of each combo box to create the SKU.
Regards,
Consider two tables Foo and Bar and consider models based on them. Now consider a one-to-one relationship between them.
Foo contains has_one :bar in it's declaration so that we're able to access Bar from Foo's objects. But then what I don't understand is why Bar needs a foreign key referencing Foo?
Shouldn't it be easier if they just compare both the ids to get the result?
I'm assuming that there will be problems with comparing both ids and I want to know what the problems are.
The problem with ids is that they store auto-incremented values. Let's consider 2 tables students and projects.
Let's assume a student can have at most 1 project. Which means he can either have a project or not.
Now consider 2 students A & B.
students table
id name
1 A
2 B
now projects table
id name
1 P1
2 NULL
in this case A has a project named as P1 but B doesn't and we're creating a null entry just to maintain and match the id of records present in projects with the students but this is not feasible in the long term. If in a school there are 1000 students then we'll have may be 500 empty rows for 500 students who are not working on a project.
That's why adding a column in projects table is a feasible solution to reduce the size of the table and maintain relationships as well and also if you're going to delete a record then the new id won't be same as the previous one as id's are auto-incremented.
now projects table
id name student_id
1 P1 1
is more feasible and flexible as well. You can make it has_many as well because a student can work on multiple projects as well.
I hope this helps you.
You can't assume that the DB engine will add the same IDs to rows in different tables. You can (I would not recommend) make an app with such behavior and implement it with triggers and constraints, but this would be a very creative (in a negative sense) approach to relational databases.
I have a new table where one of his fields is related to Table Items. I want to place a filter in one of the function fields Item Category pointing register the Item table, but do not know how this dual role. I hope it was not too confusing ..
So, I have two tables InventTable (for inverntory) and MyCartTable. I want to connect this tables so when I chose some item or items in InventTable to show in MyCartTable's grid. MyCartTable fields are ItemNumber, ProductName, PartyID;
Assuming you are working with AX 2012:
On your MyCartTable, remove the itemNumber field.
Open an other AOT windows go to Data Dictionary - Extended Data Types and locate the itemId data type. Drag and drop this data type on your table. AX will ask if you want to add a foreign key relation. Click yes, this will add a relation to the InventTable to the relations node of your table.
Now on your form, set the JoinSource property of your MyCartTable to you inventTable data source.
If you are having trouble making this work, create a new form with only those two datasources and a minimum amount of controls (like just 2 grids), this allows you to test this more easily.
I am not sure if the question title is clear enough, please feel free to edit it.
Basically, I have two DB grids which reflect two database tables, each grid showing one.
When the user selects a row in the first table (let's call it oders), I want to update the second with details of any rows matching a column of the selected row of the first table.
Say, for instance that table orders has a column customer_id and I want to populate the second table (let's call it order_details) with details of all orders from that customer, one order per row.
I can connect up 2 # datasource, query and connection to the two TDbGrids, but I am stuck as to how to code order_details SQL.
The SQL for orders is just SELECT * from orders, but the other?
I want something like SELECT * from order_details WHERE cutomer_id=<orderQuery>.currentRow.FieldByName("customer_id").AsInteger - but I don't know how to do that ...
Can someone help me with some Delphi code?
Also, once I set up that relationship, will selecting a new row in the orders DB grid automatically update the order_details DB grid? Or do I need to add code for that.
P.s I know that there is no books tag anymore (more's the pity), but can someone recommend a good book which explains the fundamentals of programming DB aware controls? I obviously need one. Thanks
Use a parameterized query for the detail (child) database:
SELECT * FROM Order_Details od WHERE od.CustomerID = :CustomerID
Then set the child query's MasterSource to the parent (Order) datasource, and the MasterFields to CustomerID. (If there are multiple columns that link the two, separate them by ;, as in CustomerID;OrderNumber.)
Every time you scroll the parent (change the selected record in the parent DBGrid), the child query will be executed with the ID of the parent row passed as a parameter automatically.