Editable detail records in Delphi DBGrid - delphi

I have a database (held in an Access .MDB file) that records staff members, and any absence they have e.g. holiday, sickness, training course, the start and end dates, and hours of productive time lost.
I then have a dbgrid bound to an "master" ADO query that finds all staff meeting the selected criteria of date range, department, search string for name, summing up the hours of productive time lost.
I have another dbgrid bound to a "detail" ADO table containing the absence records.
The desired effect is that the detail dbgrid should only contain those records from the Absence table that match the row selected in the master record (both "master" Staff and "detail" Absence tables contain a common EmployeeID field).
Though I can achieve this using ADO Queries created on the fly, changing the query each time the user moves to a different master staff record, I was hoping to use the detail DBGrid as my main method of deleting, updating, and adding additional absence records, complete with in grid lookups; so user can select record types without having to remember the code for that type.
I would also like the changes in this detail grid to be reflected in the summaries in the master dbgrid.
I have achieved this using a detail ADOTable linked as MasterDetail to the Staff Query, but need to have filtered set to True, and control the onfilterevent in code; but as the database increases in size this is getting slower and slower.
Is there anything I can do to improve this performance, or will I be forced to have the detail dbgrid as purely read-only, and all Absence records entered through another form or panel?

More information on Making the Table a Detail of Another Dataset
ADOTable2.MasterSource := DataSource1;
ADOTable2.MasterFields := 'EmployeeID';
I would also like the changes in this detail grid to be reflected in the summaries in the master dbgrid. After editing the detail table and posting any change you may use the AfterPost event to recalculate the summaries.

Related

Two UIPickerViews with Large Data Set

I would like to create a simple app in Xcode with two UIPickerViews that reference a data set where the second UIPickerView is dependent on the first one. I want to create an app where the user can select the manufacturer of a vehicle; Chevrolet, Dodge, Ford, etc. Then, the user can select the vehicle based on the first choice. For example if "Ford" was selected in the first UIPickerView, then only Ford vehicles show up in the second - F150, Focus, Mustang etc. After selecting both values, the user can search for the average price where the prices are kept in a data set. I found many examples with one UIPickerView referencing arrays, but I want to reference a much larger data set. How would I go about doing this? I am fairly new to Xcode, but I write SAS and SQL code daily.
I am assuming you have all of records saved in the database. I did something similar with 250k+ records.
Do not fetch all of your models' full representation into memory, fetch only one property (string column needed for current picker) with a DISTINCT on it - both SQLite & CoreData allow this.
Your subsequent pickers (2nd, 3rd & so on) will automatically see less data becuase of the previous filter applied (only Ford vehicles possible options).
Rule #1 applies to all of your pickers, only the relevant field as String pulled into memory with right filters.
I had no issues at all with above approach with my dataset. Not sure how big your dataset is.

Create DBGrid columns at runtime with diffrent dataset (Table)

I want to create only certain columns on my "dbgrid" at run-time, and set them to
other table field(s) or same field . How do you do that :
illustration:
I have 3 Tables :
Student(IdStudent, NameStudent ...) ,
Module(idModul,NameModule...),
Notes(idNote,idStudent,idModul,Note).
I Want to insert All Notes in one Dbgrid and names of columns of DBgrid are names of Module Table. I have No idea?
Thanks.
You cannot do this with a dbgrid; dbgrids have only one datasource and a datasource has only one dataset. If you are using an SQL compliant database you should look into a join and/or crosstab to return a single dataset. (I think this is what MartynA is talking about) Or create a clientdataset at run-time and build it with the columns/data you want if you want data-aware. I would look into using a stringgrid, listview or treeview and build the whole thing by hand.

Identifying the fact table in data warehouse design

I'm trying to design my first data mart with a star schema from an Excel Sheet containing informations about a Help Desk Service calls, this sheet contains 33 fields including different informations and I can't identify the fact table because I want to do the reporting later based on different KPI's.
I want to know how to identify the fact table measures easily and I have another question which is : Can a fact table contain only foreign keys of dimensions and no measures? Thanks in advance guys and sorry for my bad English.
You can have more than one fact table.
A fact table represents an event or process that you want to analyze.
The structure of the fact tables depend on the process or event that you are trying to analyze.
You need to tell us the events or processes that you want to analyze before we can help you further.
Can a fact table contain only foreign keys of dimensions and no measures?
Yes. This is called a factless fact table.
Let's say you want to do a basic analysis of calls:
Your full table might look like this
CALL_ID
START_DATE
DURATION
AGENT_NAME
AGENT_TENURE (how long worked for company)
CUSTOMER_NAME
CUSTOMER_TENURE (how long a customer)
PRODUCT_NAME (the product the customer is calling about)
RESOLVED
You would turn this into a fact table like this:
CALL_ID
START_DATE_KEY
AGENT_KEY
CUSTOMER_KEY
PRODUCT_KEY
DURATION (measure)
RESOLVED (quasi-measure)
And you would have a DATE dimension table, AGENT dimension table, CUSTOMER dimension table and PRODUCT dimension table.
Agile Data Warehouse Design is a good book, as are the ones by Kimball.
In general, the way I've done it (and there are a number of ways to do anything) is that the categorical data is referenced with a FKey in the fact table, but anything you want to perform aggregations on (typically as data types $/integers/doubles etc) can be in the fact table as well. So for example, a fact table might contain a hierarchy of types, such as product_category >> product_name, and it usually contains a time and/or location field as well; all of which would be referenced by a FKEY to a lookup table. The measure columns are usually integer based or money data, and are used in aggregate functions grouped by the other fields like this:
select sum(measureOne) as sum, product_category from facttable
where timeCol between X and Y group by product_category...etc
At one time a few years ago, I did have a fact table that had no measure column... because the only measure I had was based on count, which I would do dynamically by grouping different dimensions in the fact table.

capture/store when fields in database records have been changed/edited

I have a multi user database system which stores records with various fields e.g. text, date time etc.
Does anyone know of a way to capture when fields of a record have been changed/modified by a user. A bit like a audit history which displays all the events which have happened against the record.
I connect to database via tdatasource and TADQuery (fireDAC).
Thanks,
I have seen a solution where every important table has a number of triggers that fire when inserting, updating, deleting records. Those triggers save the old and the new state of the record to a corresponding "history" table.

DB grid : How to use a column of the current row of one as an index into another?

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.

Resources