SQL Database Design - Combinations of factors affecting a final value - postgresql

The price of a service may depend on various combinations of factors. Example Tables:
ServiceType_Duration (combination of 2 factors)
+-------------+----------+--------+
| ServiceType | Duration | Amount |
+-------------+----------+--------+
| Massage | 30 | 30 |
| Massage | 60 | 50 |
| Reflexology | 30 | 50 |
| Reflexology | 60 | 70 |
+-------------+----------+--------+
DiscountCode (1 factor)
+--------------+--------+---------+
| DiscountCode | Amount | Percent |
+--------------+--------+---------+
| D1 | -10 | NULL |
| D2 | NULL | -10% |
+--------------+--------+---------+
In this very simple example, a 30 minute massage with discount code D1 would have total price 30 - 10 = 20.
However, there may be many more such tables of the general format:
Factor1
Factor2
...
FactorN
Amount (possibly)
Percent (possibly)
I'm not sure about having lots of 'pricing tables' when the general format is always going to be the same. It could mean having to add/remove the same column from lots of tables.
Are the tables above OK? If not, what's the best practice for storing this sort of data?

Related

how to show absolute and percentage of total (pane) in text table format in tableau

I'm new in Tableau, I have data like this
month | gender | sales | quantity |
Jan-2022 | male/female | integer | integer |
my goal is to create a table shown below in tableau.
|----------------------------------------------------------------------------|
| | Jan-2022 |
| | male | female |
|metrics | absolute | composition | absolute | composition |
|-----------------------------------------------------------------------------
|sales | 1000 | 33% | 2000 | 66% |
|quantity | 50 | 20% | 200 | 80% |
|----------------------------------------------------------------------------|
to create the composition for each metrics i use the percentage of total then choose compute using -> pane (across). but i have no idea how to put the percentage side by side in the table.

LibreOffice calc formula: find the value for a given data based on known data

I have LibreOffice Calc spreadsheet with table that calculates cost for two services. I want calculate cost of service #2 based on known data. The known data are rates (0,80 and 0,68: its permanent) and total incl.VAT 21%. Variable data in column C (unknown): C2 always equal to C3. Based on known data, I want split "Total incl. VAT" amount into a two separate parts, service #1 and service #2 cost. In particular, I want know the 'service #2' amount with VAT. (D3 + VAT) Can someone show formula how to make this?
+---+------------+---------------+-----------------+----------+-----------------+
| | A | B | C | D | E |
+---+------------+---------------+-----------------+----------+-----------------+
| 1 | services | Rate (eur/m3) | volume, m3 | Sum(eur) | service #2 cost |
| 2 | service #1 | 0,80 | 71,00 | 56,80 | |
| 3 | service #2 | 0,68 | 71,00 | 48,28 | |
| 4 | | | Subtotal: | 105,08 | |
| 5 | | | VAT 21% | 22,07 | |
| 6 | | | Total incl. VAT | 127,15 | D3 value + VAT |
+---+------------+---------------+-----------------+----------+-----------------+

Aggregate at either of two levels

In Tableau, I am joining two tables where a header can have multiple details
Work Order Header
Work Order Details
The joined data looks like this:
Header.ID | Header.ManualTotal | Details.ID | Details.LineTotal
A | 1000 | 1 | 550
A | 1000 | 2 | 35
A | 1000 | 3 | 100
B | 335 | 1 | 250
B | 335 | 2 | 300
C | null | 1 | 50
C | null | 2 | 25
C | null | 3 | 5
C | null | 4 | 5
Where there is a manual total, use that, if there is no manual total, use the sum of the line totals
ID | Total
A | 1000
B | 335
C | 85
I tried something like this:
ifnull( sum({fixed [Header ID] : [Manual Total] }), sum([Line Total]) )
basically I need to use the ifnull, then use the manual total if it exists, or sum line totals if it doesn't
Please advise on how to use LODs or some other solution to get the correct answer
Here is a solution that does not require a level-of-detail calculation.
Just try this:
use an inner join on id of the two tables
create this calculation: ifnull(median([Manual Total]),sum([Line Total]))
insert agg(your_calculation) into your sheet

asof (aj) join strictly less than in KDB/Q

I have a quote table and trade table, and would like to list the quotes table and join in the trades table matching on timestamps strictly less than the timestamp of the trade.
For example:
q:([]time:10:00:00 10:01:00 10:01:00 10:01:02;sym:`ibm`ibm`ibm`ibm;qty:100 200 300 400)
t:([]time:10:01:00 10:01:00 10:01:02;sym:`ibm`ibm`ibm;px:10 20 25)
aj[`time;q;t]
returns
+------------+-----+-----+----+
| time | sym | qty | px |
+------------+-----+-----+----+
| 10:00:00 | ibm | 100 | |
| 10:01:00 | ibm | 200 | 20 |
| 10:01:00 | ibm | 300 | 20 |
| 10:01:02 | ibm | 400 | 25 |
+------------+-----+-----+----+
But I'm trying to get a result like:
+------------+-----+-----+----+
| time | sym | qty | px |
+------------+-----+-----+----+
| 10:00:00 | ibm | 100 | |
| 10:01:00 | ibm | 100 | 10 |
| 10:01:00 | ibm | 100 | 20 |
| 10:01:02 | ibm | 300 | 25 |
+------------+-----+-----+----+
Is there a join function that can match based on timestamps that are strictly less than time instead up-to and including?
I think if you do some variation of aj[`time;q;t] then you won't be able to modify the qty column as table t does not contain it. Instead you may need to use the more "traditional" aj[`time;t;q]:
q)#[;`time;+;00:00:01]aj[`time;#[t;`time;-;00:00:01];q]
time sym px qty
-------------------
10:01:00 ibm 10 100
10:01:00 ibm 20 100
10:01:02 ibm 25 300
This shifts the times to avoid matching where they are equal but does not contain a row for each quote you had in the beginning.
I think if you wish to join trades to quotes rather than quotes to trades as I have done you may need to think of some method of differentiating between 2 trades that occur at the same time as in your example. One method to do this may be to use the order they arrive, i.e. match first quote to first trade.
One “hacking” way I’m thinking is to just shift all trades by the minimum time unit do the aj and then shift back

Tableau: calculated field after data is reshaped

I'm trying to wrap my head around how to created a calculated field in Tableau that is calculated after the source data is pivoted. My source data is "long" i.e. normalized and looks like this:
+---------+---------+-------+
| Company | Measure | Value |
+---------+---------+-------+
| A | Sales | 100 |
+---------+---------+-------+
| A | Exp | -10 |
+---------+---------+-------+
| B | Sales | 200 |
+---------+---------+-------+
| B | Exp | -30 |
+---------+---------+-------+
(Actually every company would have more than two records, but this is simplified)
What I'd like to get out is the following where Net is calculated as Sales + (2 * Exp).
+---------+---------+-------+-------+
| Company | Sales | Exp | Net |
+---------+---------+-------+-------+
| A | 100 | -10 | 80 |
+---------+---------+-------+-------+
| B | 200 | -30 | 140 |
+---------+---------+-------+-------+
I can get the following by simply having Company as my row and Measure as my column and then sum(Value):
+---------+---------+-------+
| Company | Sales | Exp |
+---------+---------+-------+
| A | 100 | -10 |
+---------+---------+-------+
| B | 200 | -30 |
+---------+---------+-------+
But how do I calculate an additional column based on the result of pivoting Measure?
Does this get you what you need?
The crux is creating calculated fields for Exp and Sales like this:
Exp =
if [Measure] = "Exp" then [Value] end
Sales =
if [Measure] = "Sales" then [Value] end
Those become measures you can use as the columns.