({{, (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[(Subscript[class, 1]),(Subscript[class, 2]),prop]
represents a class of entities obtained by combining the properties of those pairs of entities from (Subscript[class, 1]) and (Subscript[class, 2]) for which the value of the property prop is the same for the two entities in the pair.}, {, (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[(Subscript[class, 1]),(Subscript[class, 2]),(Subscript[prop, 1])->(Subscript[prop, 2])]
combines pairs of entities from (Subscript[class, 1]) and (Subscript[class, 2]) for which the value of (Subscript[prop, 1]) of the entity from (Subscript[class, 1]) is the same as the value of (Subscript[prop, 2]) for the entity from (Subscript[class, 2]). }, {, (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[(Subscript[class, 1]),(Subscript[class, 2]),{(Subscript[pspec, a]),(Subscript[pspec, b]),…}]
combines pairs of entities for which all the property specifications (Subscript[pspec, k]) agree.}, {, (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[(Subscript[class, 1]),(Subscript[class, 2]),f]
combines pairs of entities for which the application of the entity function f yields (RefLink[True, paclet:ref/True]). }, {, (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[(Subscript[class, 1]),(Subscript[class, 2]),spec,"jspec"]
uses "jspec" to determine when to allow entities with missing properties to be included.}})

OpenersNotesSection(Spacer1)Details

(RefLink[EntityProperties, paclet:ref/EntityProperties])[CombinedEntityClass[(Subscript[class, 1]),(Subscript[class, 2]),…]] is effectively (RefLink[Join, paclet:ref/Join])[(RefLink[EntityProperties, paclet:ref/EntityProperties])[(Subscript[class, 1])],(RefLink[EntityProperties, paclet:ref/EntityProperties])[(Subscript[class, 2])]].

In (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[(Subscript[class, 1]),(Subscript[class, 2]),f], the function f must be of the form (RefLink[EntityFunction, paclet:ref/EntityFunction])[{(Subscript[e, 1]),(Subscript[e, 2])},…], where (Subscript[e, 1]) and (Subscript[e, 2]) stand respectively for entities in (Subscript[class, 1]) and (Subscript[class, 2]).

The properties in the result from (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[(Subscript[class, 1]),(Subscript[class, 2]),…] are of the form (RefLink[EntityProperty, paclet:ref/EntityProperty])[(Subscript[type, i]),…], where the (Subscript[type, i]) are the entity types of the (Subscript[class, i]).

(RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])["(Subscript[alias, 1])"->(Subscript[class, 1]),"(Subscript[alias, 2])"->(Subscript[class, 2]),…] can be used to give properties of the form (RefLink[EntityProperty, paclet:ref/EntityProperty])["(Subscript[alias, i])"->(Subscript[type, i]),…].

In (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[(Subscript[class, 1]),(Subscript[class, 2]),…], the (Subscript[class, i]) must be distinct. (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[class,"alias"->class] can be used for identical classes.

In (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[(Subscript[c, a]),(Subscript[c, b]),spec,"jspec"], the join specification jspec determines which entities (Subscript[a, i]) from class (Subscript[c, a]) and (Subscript[b, j]) from class (Subscript[c, b]) should be kept, depending on whether the condition defined by cond is met. The possible join specifications are the same as for (RefLink[JoinAcross, paclet:ref/JoinAcross]):

When a property value is absent, (RefLink[Missing, paclet:ref/Missing])["Unmatched"] is used in its place.

(RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass])[(Subscript[class, 1]),(Subscript[class, 2]),(RefLink[EntityFunction, paclet:ref/EntityFunction])[{x,y},(RefLink[True, paclet:ref/True])]] effectively implements the SQL CROSS JOIN. It is roughly equivalent to (RefLink[Outer, paclet:ref/Outer])[(RefLink[Join, paclet:ref/Join]),…] applied to the "PropertyAssociation" obtained from both classes.

OpenersPrimaryExamplesSection(Spacer1)Examples  (8)

OpenersExampleSection0(Spacer1)Basic Examples  (6)

Combine elements of period 1 with their isotopes to compare their atomic masses:

CombinedEntityClass["Isotope", (EntityClass["period 1 elements", EntityClass["Element","Period1"], "EntityClass[\"Element\", \"Period1\"]", "elements"]),"Element"->"Entity"][{EntityProperty["Isotope", "Name"],EntityProperty["Element", "AtomicMass"], EntityProperty["Isotope", "AtomicMass"]}]

A (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass]) has all the properties of both classes:

EntityProperties[CombinedEntityClass["Country", "City", "CapitalCity"-> "Entity"]]===Union[EntityProperties["Country"], EntityProperties["City"]]

Combine elements and isotopes according to a predicate:

CombinedEntityClass["Isotope", (EntityClass["period 1 elements", EntityClass["Element","Period1"], "EntityClass[\"Element\", \"Period1\"]", "elements"]),EntityFunction[{i, e},i["AtomicMass"]< e["AtomicMass"]]][{EntityProperty["Isotope", "Name"],EntityProperty["Element", "Name"]}]

Different join specifications will result in different behavior with respect to unmatched entities:

CombinedEntityClass[FilteredEntityClass["Isotope", EntityFunction[i, i["Element"]==(Entity["hydrogen", Entity["Element","Hydrogen"], "Entity[\"Element\", \"Hydrogen\"]", "element"])||i["Element"]==(Entity["lithium", Entity["Element","Lithium"], "Entity[\"Element\", \"Lithium\"]", "element"])]], (EntityClass["period 1 elements", EntityClass["Element","Period1"], "EntityClass[\"Element\", \"Period1\"]", "elements"]),"Element"->"Entity", "Inner"][{EntityProperty["Isotope", "Name"],EntityProperty["Element", "Name"]}]

CombinedEntityClass[FilteredEntityClass["Isotope", EntityFunction[i, i["Element"]==(Entity["hydrogen", Entity["Element","Hydrogen"], "Entity[\"Element\", \"Hydrogen\"]", "element"])||i["Element"]==(Entity["lithium", Entity["Element","Lithium"], "Entity[\"Element\", \"Lithium\"]", "element"])]], (EntityClass["period 1 elements", EntityClass["Element","Period1"], "EntityClass[\"Element\", \"Period1\"]", "elements"]),"Element"->"Entity", "Left"][{EntityProperty["Isotope", "Name"],EntityProperty["Element", "Name"]}]

CombinedEntityClass[FilteredEntityClass["Isotope", EntityFunction[i, i["Element"]==(Entity["hydrogen", Entity["Element","Hydrogen"], "Entity[\"Element\", \"Hydrogen\"]", "element"])||i["Element"]==(Entity["lithium", Entity["Element","Lithium"], "Entity[\"Element\", \"Lithium\"]", "element"])]], (EntityClass["period 1 elements", EntityClass["Element","Period1"], "EntityClass[\"Element\", \"Period1\"]", "elements"]),"Element"->"Entity", "Right"][{EntityProperty["Isotope", "Name"],EntityProperty["Element", "Name"]}]

CombinedEntityClass[FilteredEntityClass["Isotope", EntityFunction[i, i["Element"]==(Entity["hydrogen", Entity["Element","Hydrogen"], "Entity[\"Element\", \"Hydrogen\"]", "element"])||i["Element"]==(Entity["lithium", Entity["Element","Lithium"], "Entity[\"Element\", \"Lithium\"]", "element"])]], (EntityClass["period 1 elements", EntityClass["Element","Period1"], "EntityClass[\"Element\", \"Period1\"]", "elements"]),"Element"->"Entity", "Outer"][{EntityProperty["Isotope", "Name"],EntityProperty["Element", "Name"]}]

When combining the same type with itself, an alias must be used:

CombinedEntityClass["Cloud", "other" -> "Cloud", "CloudType"][{EntityProperty["Cloud", "Name"],EntityProperty["other" -> "Cloud", "Name"]}]//Shallow

When used with relational-database-backed entities, a (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass]) is effectively equivalent to a JOIN statement:

EntityRegister[EntityStore[RelationalDatabase[FindFile["ExampleData/ecommerce-database.sqlite"]]]]

CombinedEntityClass["customers","payments","customerNumber"][{"customerName","amount"}]//Shallow

OpenersExampleSection1(Spacer1)Scope  (2)

Define a new (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass]):

combined=CombinedEntityClass["Isotope","Element","Element"->"Entity"];

Filter the resulting class by element group:

filtered=FilteredEntityClass[combined,EntityFunction[e,e[(EntityProperty["group", EntityProperty["Element","Group"], "EntityProperty[\"Element\", \"Group\"]"])]==17]];

DeleteMissing[EntityValue[filtered, {(EntityProperty["name", EntityProperty["Isotope","Name"], "EntityProperty[\"Isotope\", \"Name\"]"]),(EntityProperty["diagnostic applications", EntityProperty["Isotope","DiagnosticApplications"], "EntityProperty[\"Isotope\", \"DiagnosticApplications\"]"])}],1,2]

Register an (RefLink[EntityStore, paclet:ref/EntityStore]):

EntityRegister[EntityStore[]]

Construct a (RefLink[CombinedEntityClass, paclet:ref/CombinedEntityClass]):

combined =CombinedEntityClass[CombinedEntityClass["book_author", "book", "book" -> "Entity"], "author", "author" -> "Entity"]

The new class has the properties of all original classes:

EntityProperties[combined]

The resulting entities are a composite of the original entities:

EntityList[combined]

({{DocumentationFooterIconsRelatedFunction.png, ({{See Also}, {(RefLink[EntityValue, paclet:ref/EntityValue])  ▪  (RefLink[EntityList, paclet:ref/EntityList])  ▪  (RefLink[EntityStore, paclet:ref/EntityStore])  ▪  (RefLink[EntityClass, paclet:ref/EntityClass])  ▪  (RefLink[JoinAcross, paclet:ref/JoinAcross])  ▪  (RefLink[Outer, paclet:ref/Outer])  ▪  (RefLink[ExtendedEntityClass, paclet:ref/ExtendedEntityClass])}})}})

({{DocumentationFooterIconsRelatedGuide.png, ({{Related Guides}, {▪(RefLinkPlain[Working with Information in Relational Databases, paclet:guide/WorkingWithRelationalDatabases])}})}})