Good way to use/design dbt relation test - dbt

I would like to have a dbt relation test for a model m_0.
models:
- name: m_0
columns:
- name: customer_id
tests:
- relationships:
to: ref('m_1')
field: id
Then I got two questions:
I'm running the model m_0 under schema s_a, how to handle the case that m_1 does not exist? There's no guarantee of m_1 must be run before m_0.
How to guarantee the relation test result is not flaky? Since m_0 and m_1 are scheduled independently, some latest id may not read from m_1 but are already in m_0.
Any good practice for writing a dbt relation test? Is there any requirements of m_0 and m_1? Such as m_1 should be a parent table of m_0?

The test is its own node, which will be downstream in the DAG from both m_0 and m_1. If you run a command like dbt build, dbt will first build m_0 and m_1 before running this relationship test. However, you are right that if you run dbt test -s m_0 and m_1 is not yet built, the test will fail. If you want to avoid this failure, you can use dbt test -s m_0 --indirect-selection=cautious and the relationship test will not run. See the docs
You should consider adding a where: config to this test, that limits the records tested in m_0. For example, where: created_at < current_timestamp - interval '1 day'. This should leave "extra" records in m_1, but this test is only concerned about missing records in m_1, so it will pass

Related

Can dbt show data dependency to non dbt table?

I'm am a big fan of the data lineage graph generated by dbt.
However, this only shows the relationships between tables & views created by dbt. Is there a way to show the dependencies to "original" tables in the database?
Say, if my dbt model creates a view of called open_orders as
SELECT * FROM orders WHERE status='Open'
I'd like to have the data lineage graph show that open_orders depends on orders.
You could use DBT Sources for that. If you create a source of your orders table, it will appear in the data lineage.

Is there a way to generate changelogs per table on an existing database?

I have an existing database on which I want to apply liquibase and generate a separate changelog for every table in order to create the current database scheme.
As far as I know, there is only the possibility to generate a single big changelog.xml for the entire database, which I did with commandline:
liquibase --driver=oracle.jdbc.OracleDriver \
--classpath=\path\to\classes:jdbcdriver.jar \
--changeLogFile=com/example/db.changelog.xml \
--url="jdbc:oracle:thin:#localhost:1521:XE" \
--username=scott \
--password=tiger \
generateChangeLog
However, I would like to generate a separate changelog.xml for every table. Let's say, if the database has three tables: butterfly, flower and bee, then there should be generated: changelog_butterfly.xml, changelog_flower.xml and changelog_bee.xml or something similar.
Any ideas much appreciated.
Judging by documentation - there is no strightforward way to do this.
Also, from logical point of view: if the goal is to have changelog per table, then where to place changesets for foreign keys? Since they belong to both tables involved - there is contradiction here :)
Probably, one way to resolve contradiction would be to place foreign keys to separate changelog. However, it looks not very convenient, especially if take into account migrating DB after initial setup.
Either way, here are some recommendations about changelog organization.

Using Git for Data History

I am currently tracking history of changes across multiple tables in an Oracle database. We are storing the entire row that changes in a separate table with the same columns as the data table, except that we also have columns for
date/time
user
version number (auto-incremented and shared by all tables)
I currently have no way of displaying this data for regular users who have no access to the database, and we have been reconsidering the whole history system for the following reasons:
Completely duplicate data structure
Need to store history info in every row that changes
Difficult to track discrete change-sets across tables
Difficult to view history at particular time
No efficient conflict detection
Therefore, I have been considering using Git to track the history. I would envision the following components
File system representation of tables (see example below)
One official repository that writes to the database on fast-forward update
This repository will be the only user that can modify the data tables.
Abort any update that causes database errors so that we can still have database-level data enforcement
File structure will be exactly mapped to the tables so that databse modification can be automatic
Local repository pools for each application
Attempt push
If fails for non-fast-forward; rebase
If rebase fails due to conflicts; abort
Write entire repository nightly to enforce Git history as single source of truth
Has anyone attempted anything similar? If so, are there any details that I should know about.
Additionally, are there any libraries or tools available that are geared to this sort of thing?
Are there better ways of doing something like this with pure Oracle SQL that can solve all my issues?
Example file structure:
(D) indicates Directory; (F) indicates File; Quoted string is file contents
Schema_USER (D)
Table_ITEM (D)
Row_ITEM_ID-24435- (D)
Column_ITEM_ID (F) : "24435"
Column_DESCRIPTION (F) : "Big Ball"
Row_ITEM_ID-24436- (D)
Column_ITEM_ID (F) : "24436"
Column_DESCRIPTION : "Small Ball"
Table_CATEGORY (D)
Row_CATEGORY_ID-35- (D)
Column_CATEGORY_ID (F) : "35"
Column_NAME (F) : "Balls"
Table_ITEM_CATEGORY (D)
Row_CATEGORY_ID-35-ITEM_ID-24436 (D)
Column_CATEGORY_ID (F) : "35"
Column_ITEM_ID (F) : "24436"

How check if exist a path between two nodes - SQL

I have the database:
Node(nno,color)
edge(eno,head,tail,weight,gno)
graph(gno,gname)
bold here represents primary key
and the graphh is directed: head -> tail
how can I build a trigger to check whether or not , with each insert of a node to the graph , the graph is connected? meaning there is a path between every two nodes
How do I even check if there is path between each two nodes ?
I am using postgreSQL
This is an X-Y problem, and most likely unworkable using a trigger: If referential integrity is to be maintained with foreign keys (definitely desirable) then by definition the insertion of a node will create a disconnected graph, and be rejected.
The solution is to have a stored procedure through which all inserts to all three tables are passed, and which only accepts connected graph additions.
Given the assumption that a given graph is already connected, then for an extension to a given graph to be accepted it is sufficient for every node in the extension to be connected to any one node in the existing graph.

Optional Database Entities

ORIGINAL (see UPDATED QUESTION below)
I am designing a new laboratory database that tests a wide variety of tests on a wide variety of sample types.
The following list is my current candidate for the list of main entities to best model the laboratory work.
For each entity, a 1-to-many relationship exists from that entity to the entity below. In other words, every entity (except REQ) has at least columns for entity_id and parent_id.
Main Entities:
REQ: Request (a form)
SAM: Sample (the material)
TST: Test (requested procedures)
SUB: ** Sub-Test (part of standard test)
TRI: ** Trial (single instance: usually for mean,range, and stddev)
MEA: Measurement (a measured number)
** Not all tests have subtests, and not all tests have trials.
Sub-tests are a set of tests grouped together by a single name for easy referencing. For example, a lot acceptance test (LAT) for a particular product is defined as the following tests: viscosity, %-nitrogen, pH, and density.
A trial is a single experiment performed multiple times for product assurance. For example, fifty bullets might be shot, and each shot is a trial. The accuracy of each bullet might be required to fall within a certain range, and the average accuracy of all fifty bullets might be required to be in a tighter range.
Question: How should I model cases when sub-tests and/or trials are not needed?
Option 1: Use a "blank" sub-test (or trial) if not needed.
Option 2: Consider sub-tests and trials to be tests (and have a test_id as a parent), so that measurements always have a test as a parent.
Option 3: Optional parents for measurement (trial, sub-test, or test) and trials (sub-test or test).
Option x: Any other option worth considering.
FYI: If required to answer the question, I will be using Oracle.
UPDATED QUESTION
In general, my schema is a heirarchy of entities where each entity (except top) must have ONE parent and (except bottom) must have at least one child. What is the best way to handle cases where an internal entity is unnecessary in certain situation, or what is the benefit/drawback to using a particular option?
Option 1 (Dummy): Use a "dummy" entry to indicate entity does not apply in this case.
Option 2 (Rollup): Roll-up optional entities into next higher parent entity.
Option 3 (Pick-a-Parent): Entity (C) below optional entity (B) with required entity (A) must have ONE parent but the parent can be either the optional entity (B) or the next higher one (A).
Option x: Any other option worth considering.
Addressing your simplified question:
Given a hierarchy as you've described, if I found that some levels in the hierarchy were optional, I would question whether a hierarchy really mapped well to my domain. I would consider drawing my relations differently, or redefining the entities in my schema.
I don't think a more detailed answer to the general question is possible in a short space like this, since figuring out the best representation of a domain is a) hard, and b) very specific to the particular domain.
Use Outer Joins. (RIGHT OUTER JOIN and LEFT OUTER JOIN).
They were made specifically for this.
< Edit > This is my first post. Based on the comments, I'll be adding a second post.
Here's my take on an architectural first pass. This stuff generally requires a LOT of back-and-forth with the subject matter experts to get right.
"Test" means one of:
- Take an action, measure results
- Take several actions (subtests), measure results for each
- Make no tests whatsoever (yet you can still have measurements -- ?)
I'd configure this as a "parent" Test table and a child "SubTest" table, where Test can have 0 or more related SubTests, and every SubTest must be related with one and only one Test. (If a test has only one SubTest, enter it in its own table, don't try and track SubTests in the Test table.)
Trials can only exist if there are SubTests. Therefore, Trials are a child of the SubTest table; SubTests can have zero or more Trials, and Trials must be related with one and only one SubTest.
Measures only exist if there are Trials. Therefore, repeat the above, with Measures as a child of Trials.
Can there be SubTests without Trials (or Tests)? If so, then don't enter any Trials.
Can there be Measures without Trials? If no, you don't need any Trials (or SubTests). If yes (?), once again enter some properly labeled dummy/placholder SubTests or Trials as necessary.
Again, this is rudimentary, and more interviews with the folks driving requirements is required.
As others have remarked it is hard for us to give a definitive answer without understanding more about your domain. You have attempted to distill a lot of business rules into a couple of paragraphs but some important information has been lost. Specifically, it is not possible to be sure whether two entities are genuinely distinct without knowing their attributes. Having said all which, let's have a go.
A TEST is a single procedure. Despite containing the word "test" a LAT is not a TEST in its own right but is rather a pre-defined set of such procedures. I would model this scenario as an entity TEST with an optional parent entity, which I would prefer to call TEST_GROUP (as that is what it is) but it is best to use the domain name, SUB_TEST.
A TRIAL appears to be distinct from a TEST, so model it as a separate entity. Therefore you have a choice when it comes to MEASUREMENT: you can have one entity with two optional foreign keys or you can have TEST_MEASUREMENT and TRIAL_MEASUREMENT. Choosing which road to go depends on the characteristics and usage profile.
The following is an initial stab at the entity relationships. This would be the point in the project when the user goes, "Oh no, that is not what I meant at all."
create table sample (
sample_id number not null
, constraint samp_pk primary key (sample_id)
)
/
create table sub_test (
sub_test_id number not null
, sample_id number not null
, constraint subt_pk primary key (sub_test_id)
, constraint subt_samp_fk foreign key (sample_id)
references sample (sample_id)
)
/
create table test (
test_id number not null
, sample_id number not null
, sub_test_id number
, constraint tst_pk primary key (test_id)
, constraint tst_samp_fk foreign key (sample_id)
references sample (sample_id)
, constraint tst_subt_fk foreign key (sub_test_id)
references sub_test (sub_test_id)
)
/
create table trial (
trial_id number not null
, test_id number not null
, constraint trl_pk primary key (trial_id)
, constraint trl_tst_fk foreign key (test_id)
references test (test_id)
)
/
create table measurement (
measurement_id number not null
, trial_id number
, test_id number
, constraint meas_pk primary key (measurement_id)
, constraint meas_tst_fk foreign key (test_id)
references test (test_id)
, constraint meas_trl_fk foreign key (trial_id)
references trial (trial_id)
, constraint measurement_ck check (
(test_id is not null and trial_id is null)
or (test_id is null and trial_id is not null)
)
/
Edit
Addressing your more generic question.
Option 1 (Dummy)
Never use a dummy record. It's is like using a magic value instead of a null. The solution is worse than the problem it solves.
Option 2 (Rollup)
This can work when the parent and the child have the same attributes. But it is not a viable solution if they have different columns, or if they are different dependencies. Even if they have identical data structures but different business uses it may still be a problem.
Option 3 (Pick-a-Parent)
This would be my preferred solution. The snag is the need for a check constraint to ensure that one (and only one) of the eligible foreign keys has been populated. You also need to guard against allowing too many parents/grandparents/great-grandparents into the mix.
I am not entirely sure I understand the details of your question, but it sounds like you should have the following:
Table Test
test_id, request, sample, test
Table SubTest
subtest_id, test_id (foreign key to Test)
Table Trial
trial_id, trial_name, measurement, subtest_id
So, Test is a collection of subtests (possibly just one subtest), and a subtest is a collection of Trials (possibly just one trial)
I'm not entirely certain I understand your domain, but could you do something like this?
Tests has a parent_test_id column, which can be NULL (when set, this is a subtest).
Trials has a test_id column. (All tests have at least one trial, since you did a thing and had at least one measurement, right?)
Measurements has a trial_id column.
This does seem to violate your premise, since it stipulates that all tests have at least one trial, so it's possible I misunderstand the requirements. How can you have a test with no trials?
Anyway, if necessary, you could put both a trial_id and a test_id on Measurements, possibly with a constraint that one or the other must be NULL (and the other must be set).
I'll take a second stab at this one, based on the feedback from my first post. The key thing to understand is that design and architecture can be highly iterative, and I doubt you'll get the ideal model without a lot of back-and-forth--something that doesn't play out to well on Stack Overflow. Odds are you'll take the ideas posted (APC has some good ones), bounce them around with the people you work with, and come up with something that'll work.
My goal these days when designing databases is to try and produce a fully normalized model. Once you've got that, if it doesn't seem reasonable or practical you can denormalize for efficiency, expediency, or whatever -- but the key thing is you denormalize after you've found the ideal model. If you stop normalization before you get to fully normalized, you haven't denormalized, you've just got a sloppy model.
Here's the entities I see to-date:
What you've labeled as the top-level test, for purposes of clarity here I'm going to call an Exam. You define an exam and all its contents (below), and people contact your laboratory to run these exams on their problems.
For any given exam performed for a customer, you run a bunch of Tests. Any given test may be used by (required by?) any number of exams.
Often, you get a set of Tests that are done together for more than one Exam. If there are properties that apply to the specific set of Tests, you might want to identify each set as its own entity. Call these TestGroups. However, if these are only used associate a specific set of Tests with one or more Exams, you might not get any particular benefit our of defining them as their own entity. (These are your SubTests.)
So, an Exam "has" or "contains" one or more Tests. Alternatively, Exams are related with one or more TestGroups. However, trying to relate an Exam with zero or more TestGroups and zero or more individual Tests will produce an overly complex model (let alone physical implmentation), and I'd really want to avoid that. Perhaps a TestGroup can contain a single Test, so Exams only reference TestGroups? Maybe an Exam can only be related to one TestGroup -- in which case that'd be the "many to many" table relating Exams with Tests. This depends on further discussion of requirements with the subject matter experts.
So you have Exams -- Exam definitions, really -- related somehow or other with multiple Tests. Next up, you have a "paid instance" of an Exam (customer X comes in and pays you to test his Widgets). Call this a CustomerExam; it has all the contact and billing info, identifies the Exam to be run, and thus is related to the Tests to be performed for the customer. (There's probably a Customer entity out there too...?)
Trials are perfomed for the Tests that are part of a CustomerExam. They don't relate with the Exam or the Test, they are an instance of the Trial being performed. (Seems safe to assume that the "meaning/definition" of a Trial would actually be part of a Test--for example, if Test = Is gun accurate, then the work required by a Trial for that Test = fire gun 50 times and measure). So as Trials are performed for the Tests of a given CustomerExam. Are they performed once, or more than once? (Is a trial to fire the gun 50 times, or is each shot counted as a trial? What if they do two rounds of 50 shots?) Whatever, the attributes of the Trial event are stored here -- when it happened, who did it, special notes/circumstances, whatever.
Measures are produced by (or for?) Trials. The meaning/definition of each measure is actually part of the definition of a Trial (which is part of the definition of a Test); the event of the Trial produces specific values for the defined/anticipated Measures. The assumption is that a Trial will generate zero (?) or more Measures, so Measures are their own entity.
Looking back at this, it seems like there's some form of implicit double stucture: a set of tables to define available Exams, Tests, Trials, and Measures (what can be examined, how can it be tested, what shall we measure) and a companion set of tables to track specific instances of each (who wanted it, who did the work, when did they do it, what were the results)
I've got to have way over-anazled this problem. The key thing here is, as with all design sessions, in posing ideas and asking questions, did they generate your own ideas, questions, or answers?