The objective of this talk is getting you started with the main concepts of working with RelationalDatabases through the Entity framework in the Wolfram Language.
Outline
Outline
◼
Philosophy
◼
Classes of entities
◼
Inspection
◼
Querying
◼
Relations
◼
EmbeddedSQL and ExternalEvaluate
◼
Q&A
Philosophy
Philosophy
EntityValue[class,properties]
First argument: EntityClass (and related heads)
First argument: EntityClass (and related heads)
◼
Fully inert and symbolic
◼
Represents all the data
◼
Rows
Second argument: EntityProperty (usually plural)
Second argument: EntityProperty (usually plural)
◼
Projection
◼
Columns
Principles
Principles
◼
Resolution only happens when EntityValue is called
◼
EntityList considered dangerous (/s)
◼
1 EntityValue = 1 SQL query
Classes of entities
Classes of entities
EntityClass
EntityClass
Legacy, can do basic filtering and sorting
FilteredEntityClass
FilteredEntityClass
Full-fledged filtering (WHERE)
ExtendedEntityClass
ExtendedEntityClass
Annotations, renamings
SampledEntityClass
SampledEntityClass
Roughly follows the Take syntax (LIMIT, OFFSET)
SortedEntityClass
SortedEntityClass
Like SortBy (ORDER BY)
AggregatedEntityClass
AggregatedEntityClass
2-ary version performs aggregations, 3-argument version groups and aggregates (GROUP BY)
CombinedEntityClass
CombinedEntityClass
Similar to JoinAcross, but supports more complex statements (JOIN)
UnionedEntityClass
UnionedEntityClass
Most complex set operation, supports SameTestProperties (UNION, UNION ALL, DISTINCT ON)
IntersectedEntityClass
IntersectedEntityClass
Also supports SameTestProperties (INTERSECT)
ComplementedEntityClass
ComplementedEntityClass
Also supports SameTestProperties (EXCEPT)
Classes of entities (cont.d)
Classes of entities (cont.d)
◼
Like Lego: each class of entities is takes one (or more) classes of entities as arguments
◼
Completely inert and symbolic
◼
You can reason about their EntityProperties without executing
Inspection
Inspection
In[]:=
schema=RelationalDatabase[FindFile["ExampleData/ecommerce-database.sqlite"]]
Out[]=
RelationalDatabase
Top-level properties
Top-level properties
In[]:=
schema["Properties"]
Out[]=
{Tables,Connection}
In[]:=
schema["Tables"]
Out[]=
{productlines,payments,offices,products,orderdetails,employees,orders,customers}
Table-level properties
Table-level properties
In[]:=
schema["orders","Properties"]
Out[]=
{Columns,ForeignKeys,Name,PrimaryKey,UniquenessConstraints,Indexes}
In[]:=
schema["orders","Columns"]
Out[]=
{orderNumber,orderDate,requiredDate,shippedDate,status,comments,customerNumber}
Column-level properties
Column-level properties
In[]:=
schema["orders","orderNumber","Properties"]
Out[]=
{NativeTypeString,Default,Indexed,Name,Nullable}
In[]:=
schema["orders","orderNumber","NativeTypeString"]
Out[]=
INTEGER
Inspection: EntityStore
Inspection: EntityStore
In[]:=
store=EntityStore[schema]
Out[]=
◼
Bold properties are primary keys ⇒ CanonicalName
◼
Underlined properties are relations ⇒ Entity- or EntityClass-valued properties
◼
→ means one-to-one (outgoing foreign key)
◼
← means one-to-many (incoming foreign key)
In[]:=
EntityRegister[store]
Out[]=
{productlines,payments,offices,products,orderdetails,employees,orders,customers}
Querying
Querying
In[]:=
EntityValue["offices","officeCode"]
Out[]=
{1,2,3,4,5,6,7}
In[]:=
EntityValue["offices",{"city","country"},"PropertyAssociation"]
Out[]=
{citySan Francisco,countryUSA,cityBoston,countryUSA,cityNYC,countryUSA,cityParis,countryFrance,cityTokyo,countryJapan,citySydney,countryAustralia,cityLondon,countryUK}
In[]:=
EntityValue[FilteredEntityClass["offices",EntityFunction[x,x["country"]"USA"]],"city"]
Out[]=
{San Francisco,Boston,NYC}
In[]:=
EntityValue["offices",{"state",EntityFunction[o,MissingQ[o["state"]]]}]
Out[]=
{{CA,False},{MA,False},{NY,False},{Missing[NotAvailable],True},{Chiyoda-Ku,False},{Missing[NotAvailable],True},{Missing[NotAvailable],True}}
Querying (composition)
Querying (composition)
Count how many customers per city and country we have
In[]:=
aggr=AggregatedEntityClass["customers","customerCount"EntityFunction[c,Length[c["customerNumber"]]],{"city","country"}];
In[]:=
EntityValue[aggr,"PropertyAssociation"]
Well, this is unsorted, let’s sort it:
Querying (what happens under the hood?)
Querying (what happens under the hood?)
Who is making orders on Sundays?
Relations
Relations
What’s the overall structure of the database?
Here is a naked column:
Here is the same column expressed as an Entity:
And the reverse relation:
A more complicated example:
The same thing without relations
Aggregation-less aggregations
EmbeddedSQL and ExternalEvaluate
EmbeddedSQL and ExternalEvaluate
Useful for things we don’t or can’t support
Supports binding things from the outer query
What if I want to have query-level EmbeddedSQL?
Really arbitrary stuff:
CITE THIS NOTEBOOK
CITE THIS NOTEBOOK
Wolfram R&D LIVE: Relational Databases in the Wolfram Language
by Carlo Barbieri
Wolfram Community, STAFF PICKS, April 25 2023
https://community.wolfram.com/groups/-/m/t/2907390
by Carlo Barbieri
Wolfram Community, STAFF PICKS, April 25 2023
https://community.wolfram.com/groups/-/m/t/2907390