Interdependent MySQL Calculation Triggers - mysql

I am currently developing a large MySQL database that has 4 main tables within it as follows:
Table Damage Loop
---------------------------------------------------------
| Damage Loop No | Description | Minimum Remaining Life |
---------------------------------------------------------
| abc | pie | 5 |
| xyz | apple | 15 |
| ... | ... | ... |
---------------------------------------------------------
Table Equipment
---------------------------------------------------------------------------
| Damage Loop No | Equipment No | Description | Minimum Remaining Life |
---------------------------------------------------------------------------
| abc | X100 | pie slice 1 | 5 |
| abc | X200 | pie slice 2 | 20 |
| xyz | B100 | apple slice 1 | 15 |
| xyz | B200 | apple slice 2 | 30 |
| ... | ... | ... | ... |
---------------------------------------------------------------------------
Table Monitoring Location
--------------------------------------------------------------------------------------------------------------------------------------
| Damage Loop No | Equipment No | CML No | Description | Corrosion Rate | Wall Thickness | Allowable Wall Thickness | Remaining Life |
--------------------------------------------------------------------------------------------------------------------------------------
| abc | X100 | 1 | Location 1 | 0.2 | 3 | 2 | 5
| abc | X100 | 2 | Location 2 | 0.2 | 4 | 2 | 10
| xyz | B100 | 1 | Location 1 | 0.2 | 5 | 2 | 15
| xyz | B100 | 2 | Location 2 | 0.2 | 6 | 2 | 20
| ... | ... | ... | ... | ... | ... | ... | ...
--------------------------------------------------------------------------------------------------------------------------------------
Table Inspection
---------------------------------------------------------------------------
| Damage Loop No | Equipment No | CML No | Inspection No | Wall Thickness |
---------------------------------------------------------------------------
| abc | X100 | 1 | 1 | 5 |
| abc | X100 | 1 | 2 | 10 |
| abc | X100 | 1 | 3 | 3 |
| ... | ... | ... | ... | ... |
---------------------------------------------------------------------------
Now these tables all have interdependent calculations that I would like to perform as triggers based on what values the user changes in the database. For example if we look at [Damage Loop].[Minimum Remaining Life]. It is calculated as follows...
[Damage Loop].[Minimum Remaining Life] = Min([Equipment].[Minimum Remaining Life] For Associated Records)
Where [Equipment].[Minimum Remaining Life] is calculated as follows...
[Equipment].[Minimum Remaining Life] = Min([Monitoring Location].[Remaining Life] For Associated Records)
Where the [Monitoring Location].[Remaining Life] is calculated as follows...
[Monitoring Location].[Remaining Life] = ([Wall Thickness] - [Allowable Wall Thickness])/[Corrosion Rate]
Where...
[Wall Thickness] = Min([Inspection].[Wall Thickness] for associated records)
[Allowable Wall Thickness] = Manual input
[Corrosion Rate] = Manual input
So if the user changes the [Monitoring Location].[Allowable Wall Thickness] field I would like the trigger to only recalculate the following fields...
[Monitoring Location].[Remaining Life]
[Equipment].[Remaining Life]
[Damage Loop].[Remaining Life]
But if the user changes the [Inspection].[Wall Thickness] field I would like the trigger to perform the following calculations...
[Monitoring Location].[Wall Thickness]
[Monitoring Location].[Remaining Life]
[Equipment].[Remaining Life]
[Damage Loop].[Remaining Life]
i.e. only re-calculate the fields that are dependent on the field the user changes.
I basically have hundreds of calculations like these in my system and would like a really efficient and structured way of only recalculating dependent fields based on what the user changes in the database. I would like to avoid having to write specific triggers for every possible case in the system. Any ideas of how I can achieve this?

Related

Precalculate numbers of records for each possible combination

I have a mySQL database table containing cellphones information like this:
ID Brand Model Price Type Size
==== ===== ===== ===== ====== ====
1 Apple A71 3128 A 40
2 Samsung B7C 3128 B 20
3 Apple ZX5 3128 A 30
4 Huawei Q32 2574 B 40
5 Apple A21 2574 A 25
6 Apple A71 3369 A 30
7 Samsung A71 7413 C 40
Now I want to create another table, that would contain counts for every possible combination of the parameters.
Params Count
============================================== =======
ALL 1000000
Brand(Apple) 20000
Brand(Apple,Samsung) 40000
Brand(Apple),Model(A71) 7100
Brand(Apple),Type(A) 6000
Brand(Apple),Model(A71,B7C),Type(A,B) 7
Model(A71) 12514
Model(A71,B7C) 26584
Model(A71),Type(A) 6521
Model(A71),Type(A,B) 8958
Model(A71),Type(A,B),Size(40) 85
And so on for every possible combination. I was thinking about creating a stored procedure (that i would execute periodically), that would perform queries with every existing condition like that, but I am a little stuck on how exactly should it look like. Or is there a better way how to do this?
Edit: the reason why I want to store information like this is to be able to show number of results in filter in client application, like in the picture.
I would like to create index on the Params column to be able to get the Count number for given hash instantly, improving performance.
I also tried querying and caching the values dynamically, but I want to try this approach as well, so I can compare which one is more effective.
This is how I am calculating the counts now:
SELECT COUNT(*) FROM products;
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple');
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple', 'Samsung');
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple') AND Model IN ('A71');
etc.
You can use a ROLLUP for this.
SELECT
model, type, size, COUNT(*)
FROM mytab
GROUP BY 1, 2, 3
WITH ROLLUP
With your sample data, we get the following:
| model | type | size | COUNT(*) |
| ----- | ---- | ---- | -------- |
| A21 | A | 25 | 1 |
| A21 | A | | 1 |
| A21 | | | 1 |
| A71 | A | 30 | 1 |
| A71 | A | 40 | 1 |
| A71 | A | | 2 |
| A71 | C | 40 | 1 |
| A71 | C | | 1 |
| A71 | | | 3 |
| B7C | B | 20 | 1 |
| B7C | B | | 1 |
| B7C | | | 1 |
| Q32 | B | 40 | 1 |
| Q32 | B | | 1 |
| Q32 | | | 1 |
| ZX5 | A | 30 | 1 |
| ZX5 | A | | 1 |
| ZX5 | | | 1 |
| | | | 7 |
The subtotals are present in the rows with null values in different columns, and the total is the last row where all group by columns are null.

MS Access Report Field Value as Heading with Other Field Values Beneath in Table

In a Microsoft Access report, how can I display each record of a field as a column heading with the records of other fields in that columns records beneath it.
My query gives me data in the following format:
| ID | Item | Item Characteristic 1 | Item Characteristic 2 | Other Fields |
|:--:|:------:|:---------------------:|:---------------------:|--------------|
| 22 | Code 1 | Blue | 48 | … |
| 22 | Code 2 | Red | 50 | … |
| 22 | Code 3 | Green | 99 | … |
I'd like to have on my report to look something like this:
| Heading | Data True to All Records1 | More Data True to All Records2 | |
|:---------------------:|:-------------------------:|:------------------------------:|:------------:|
| ------------ | ------------ | ------------ | ------------ |
| Item | Code 1 | Code 2 | Code 3 |
| Item Characteristic 1 | Blue | Red | Green |
| Item Characteristic 2 | 48 | 50 | 99 |
| Other Fields | … | … | … |
| ------------ | ------------ | ------------ | ------------ |
| Footer | Data True to All Records3 | More Data True to All Records4 | |
Currently, I can only get data in the format:
| Heading | | |
|:-------:|:-----:|:--:|
| ---- | | |
| Code 1 | Blue | 48 |
| | | |
| Code 2 | Red | 50 |
| | | |
| Code 3 | Green | 99 |
| --- | | |
| Footer | | |
Where each record is resulting in a new 'row' in the report.
Can anyone help?
Table needs a unique record identifier - an autonumber type field should serve, then consider the following.
Query1:
SELECT RecID, ID, "Item" AS Category, Item AS Data FROM Tablename
UNION SELECT RecID, ID, "ItemChar1", ItemChar1 FROM Tablename
UNION SELECT RecID, ID, "ItemChar2", ItemChar2 FROM Tablename;
Query2:
TRANSFORM First(Query1.Data) AS FirstOfData
SELECT Query1.ID, Query1.Category
FROM Query1
GROUP BY Query1.ID, Query1.Category
PIVOT Query1.RecID;
For posterity, I resolved this by setting out a table of unbound labels.
I gave each of these labels a control name of x-y, where x was the column number and y was the row number.
I then looped through each column and row and changed the caption of the label to the value from my RecordSet.
(Form("FormName").Controls.Item(x & "-" & y)).Caption = .Fields("FieldName")

Get average from nested eloquent relationship

I would like to calculate average from nested relationship between eloquent models. So, let's say, I have 3 tables called programs, activities and statistics.
For simplicity sake, I will try to minimize the structure as follows:
program table:
-------------
| id | name |
-------------
| 1 | Foo |
| 2 | Bar |
-------------
activities table:
-----------------------------------
| id | program_id | name |
-----------------------------------
| 1 | 1 | Foo 1 |
| 2 | 1 | Foo 2 |
| 3 | 1 | Foo 3 |
| 4 | 2 | Bar 1 |
| 5 | 2 | Bar 2 |
-----------------------------------
statistics table:
-----------------------------------
| id | activity_id | type | score |
-----------------------------------
| 1 | 1 | A | 25 |
| 2 | 1 | B | 20 |
| 3 | 1 | A | 22 |
| 4 | 2 | A | 27 |
| 5 | 2 | B | 24 |
| 6 | 3 | A | 23 |
-----------------------------------
Now, what I want to get is the average of score of a program with specific type of statistic. I defined relationship in models, and tried following code, but no avail:
$program = Program::find(1);
$avg = $program->activities->where('statistics.type', 'A')->avg('statistics.value');
$avg always 0 or null if there is no activities in program, even without where clause.
i'm sure that i defined the relationship correctly because $program->activities returns a sets of activities and $activity-> statistics return a sets of statistics as well.
Any ideas?
You can use whereHas() like this:
Statistics::whereHas('activity', function ($q) use($programId) {
$q->where('program_id', $programId);
})
->where('type', 'A')
->avg('score');
Make sure you've defined activity relationship which should be "statistics belongsTo() activity".

MYSQL multi JOIN from different tables

I have multiple MYSQLI tables for multiple details and options about a touristic package.
I have package containing the main information, then I have package_option which contains unknown number of options added to the package, and there's package_images which contains the images.
I want to get all the information in one query, but it's prooving a difficult task. Let me explain.
I've used JOIN with but the problem was if the package_option had 3 options and the package_images had 6 images, the result was a 6*4 plus 1 (package) result table.
I would like a result containing all the fields, as many as they originaly are in the tables, not multiplied for each match in every table.
For example, the table I aim for looks like that:
-------------------------------------------------------------------------
| ID | name | description | price | option | image | size | explanation |
-------------------------------------------------------------------------
| 1 | test | some desc | 50 $ | opt. 1 | img1 | 30 | |
| | | | | opt. 2 | img2 | | |
| | | | | opt. 3 | img3 | | |
| | | | | | img4 | | |
| | | | | | img5 | | |
| | | | | | img6 | | |
Right now, the above table gets populated in every field, but it's multiplied, so I don't get only 6 rows, but 24.
I did a lot of JOINS, I'm not a beginer, which is even more frustrating, but it's the first time I try to do that, a select from multiple tables with different columns and unknown number of rows.
package_option and package_images looks like that:
-------------------------------------
| ID | package_id | option / image |
-------------------------------------
| 1 | 1 | opt. 1 / img 1 |
| 2 | 2 | opt. 2 / img 2 |
..... etc
so I don't know how many rows I'll have.
Thank you in advance for t

SSRS Indicator affecting group by

I am filtering a tablix and then grouping both rows (total of 3) and columns (total of 2), with no detail section. One row only has an applicable value for one of the grouped columns. The group by places all of the values in the correct cell. However, if I add an indicator, the row without an applicable value for the column inherits data from another row. Adding the field that the indicator is based on does not make this change. This row (and others that are working correctly) has a null value for the indicator in the first column, IE it shouldn't show up.
Dataset:
+---------+---------------+-----------+---------+
| Family | Description | Value |Indicator|
+---------+---------------+-----------+---------+
| A | Something | 5 | 2 |
| A | Another | 2 | 1 |
| B | Yearly Plans | 63 | null |
| B | Weekly Plans | 4 | 2 |
| B | Yearly Qual | .4 | 1 |
| B | Weekly Qual | .2 | 1 |
| B | Purchased % | .76 | null |
+---------+---------------+-----------+---------+
Filter tablix for Family = B
Row Group: =iif(Field!Description.Value like "Plans","Plans",iif(Field!Description.Value like "Qual","Qualifying",Field!Description.Value))
Column Group: iif(Field!Description.Value like "Yearly*","YTD","Weekly")
Result without indicators:
+---------------+------------+----------+
| Description | Weekly | YTD |
+---------------+------------+----------+
| Qualifying | .2 | .4 |
| Plans | 4 | 63 |
| Purchased % | .76 | |
+---------------+------------+----------+
Result with indicators (Based on indicator field):
+---------------+--------+---+--------+---+
| Description | Weekly | | YTD | |
+---------------+--------+---+--------+---+
| Qualifying | .2 | - | .4 | - |
| Plans | 4 | + | 63 | |
| Purchased % | .76 | | .4 | - |
+---------------+------------+--------+---+
What it SHOULD be:
+---------------+--------+---+--------+---+
| Description | Weekly | | YTD | |
+---------------+--------+---+--------+---+
| Qualifying | .2 | - | .4 | - |
| Plans | 4 | + | 63 | |
| Purchased % | .76 | | | |
+---------------+------------+--------+---+
I have patched the current problem by unioning in a Yearly Purchased % row with null values, but there must be something else going one. Is there something in how indicator's behave that would add values that aren't part of a group?
I realized the same thing, could it be a bug in SSRS indicators, as workaround, you can write an expression inside the cell to check against another cell and investigate if there is data then show the value inside the cell, if not then write nothing.
like: =iif(count(Fields!Field1.Value)>1,"",Fields!Field2.Value)