Fyi using the RANK operator with a rva
Posted: Fri Aug 17, 2018 4:51 am
The RANK operator is extremely useful especially when used with rva's (relation valued attributes).
But in this context you have to be careful.
For example, given this relation:
Suppose you want to GROUP attribute KEY. over attribute ID and create attribute RANK. using
attribute KEY. for the ranks. You want to end up with the following result (or at least close to it):
Rva GRP.RVA is the result of GROUP using KEY. and rva RANKS.RVA is the relation with KEY.
and the rank attribute RANK.
You might think this query should do it:
But if you execute the query you will get a fatal exception. The salient part of the error is this:
This error suggests that Rel can't determine the attribute(s) in rva GRP.RVA. GRP.RVA was initially
defined with just attribute KEY. but the ranking implies attributes KEY. and RANK. so which definition
should be used (perhaps Rel is also ignoring the relevance of RANKS.RVA which is where attribute RANK.
belongs).
In any case there are some simple ways to remove any ambiguities and get the query working.
One way is to show the degree of GROUP.RVA consistently. The degree of GROUP.RVA is 1 when its
formed so use a projection(with KEY.) with it in RANKS.RVA so the degree is always 1.
This query returns the result mentioned above.
Another way is to simply remove GRP.RVA from the result.
This query returns just ID and RANKS.RVA and may be more appropriate when GRP.RVA is no longer needed.
Also if you put a query with this error in an operator the operator will compile
with the error hidden until the operator is executed.
But in this context you have to be careful.
For example, given this relation:
Code: Select all
REL{TUP{KEY. 1,ID "A"},
TUP{KEY. 2,ID "A"},
TUP{KEY. 3,ID "B"},
TUP{KEY. 4,ID "B"},
TUP{KEY. 5,ID "B"}}
attribute KEY. for the ranks. You want to end up with the following result (or at least close to it):
Code: Select all
RELATION {ID CHARACTER, GRP.RVA RELATION {KEY. INTEGER}, RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER}} {
TUPLE {ID "A", GRP.RVA RELATION {KEY. INTEGER} {
TUPLE {KEY. 1},
TUPLE {KEY. 2}
}, RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER} {
TUPLE {KEY. 1, RANK. 1},
TUPLE {KEY. 2, RANK. 2}
}},
TUPLE {ID "B", GRP.RVA RELATION {KEY. INTEGER} {
TUPLE {KEY. 3},
TUPLE {KEY. 4},
TUPLE {KEY. 5}
}, RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER} {
TUPLE {KEY. 3, RANK. 1},
TUPLE {KEY. 4, RANK. 2},
TUPLE {KEY. 5, RANK. 3}
}}
}
and the rank attribute RANK.
You might think this query should do it:
Code: Select all
REL{TUP{KEY. 1,ID "A"},
TUP{KEY. 2,ID "A"},
TUP{KEY. 3,ID "B"},
TUP{KEY. 4,ID "B"},
TUP{KEY. 5,ID "B"}}
GROUP{KEY.} AS GRP.RVA
EXTEND {RANKS.RVA:=GRP.RVA{KEY.} RANK(ASC KEY. AS RANK.)}
Code: Select all
org.reldb.rel.exceptions.ExceptionFatal: RS0452: Bad tuple. Heading TUPLE {KEY. INTEGER, RANK. INTEGER} says degree = 2 but tuple TUPLE {1} says degree = 1.
defined with just attribute KEY. but the ranking implies attributes KEY. and RANK. so which definition
should be used (perhaps Rel is also ignoring the relevance of RANKS.RVA which is where attribute RANK.
belongs).
In any case there are some simple ways to remove any ambiguities and get the query working.
One way is to show the degree of GROUP.RVA consistently. The degree of GROUP.RVA is 1 when its
formed so use a projection(with KEY.) with it in RANKS.RVA so the degree is always 1.
Code: Select all
REL{TUP{KEY. 1,ID "A"},
TUP{KEY. 2,ID "A"},
TUP{KEY. 3,ID "B"},
TUP{KEY. 4,ID "B"},
TUP{KEY. 5,ID "B"}}
GROUP{KEY.} AS GRP.RVA
EXTEND {RANKS.RVA:=GRP.RVA{KEY.} RANK(ASC KEY. AS RANK.)}
Another way is to simply remove GRP.RVA from the result.
Code: Select all
(REL{TUP{KEY. 1,ID "A"},
TUP{KEY. 2,ID "A"},
TUP{KEY. 3,ID "B"},
TUP{KEY. 4,ID "B"},
TUP{KEY. 5,ID "B"}}
GROUP{KEY.} AS GRP.RVA
EXTEND {RANKS.RVA:=GRP.RVA RANK(ASC KEY. AS RANK.) }){ALL BUT GRP.RVA}
Code: Select all
RELATION {ID CHARACTER, RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER}} {
TUPLE {ID "A", RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER} {
TUPLE {KEY. 1, RANK. 1},
TUPLE {KEY. 2, RANK. 2}
}},
TUPLE {ID "B", RANKS.RVA RELATION {KEY. INTEGER, RANK. INTEGER} {
TUPLE {KEY. 3, RANK. 1},
TUPLE {KEY. 4, RANK. 2},
TUPLE {KEY. 5, RANK. 3}
}}
}
with the error hidden until the operator is executed.