I have two tables like so:
create table doi (
id number primary key not null,
-- Other columns omitted
);
create table doi_membership (
id number primary key not null,
doi_id number not null, --foreign key to doi.id
key_1 number not null,
key_2 number not null,
-- Other columns omitted
);
I have a set of key_1, key_2 pairs and I want to see if there is a doi that contains the complete set of the given key_1, key_2 pairs and nothing more. I can’t seem to think of the SQL necessary to do this. I am using an oracle database if that helps. Any ideas?
Update:
I don’t think I explained this very well so I will give an example.
Conceptually, a single DOI contains a list of key_1, key_2 pairs. I have my own list of key_1, key_2 pairs and I want to see if there exists a DOI where its list of pairs exactly matches my list of pairs.
So, lets say there is a DOI that has the following list of key_1, key_2 pairs (each of these rows is a separate doi_membership row related to the same doi):
1, 2
3, 4
5, 6
And another DOI with the following list of pairs:
1, 2
3, 4
5, 6
7, 8
The set of pairs that I have are
1, 2
3, 4
5, 6
I want to match the first DOI given because its set of pairs and my set of pairs match exactly. The second DOI should not be matched.
I hope that clears things up.
I think the best way to approach set membership is using the
HAVINGclause in SQL. The idea is to group the elements of the set together, in this case, the membership records for each doi, and then do tests at the individual level.For instance, the following having clause would check that keyval1 is present:
It does this by summing the number of records with
keyval_1 = <keval1>. If there is more than 0, then “doi_id” meets the condition.Your conditions are a bit mroe complicated because you are looking at pairs of values. One way to solve this is by concatenating the values together (not necessary, but it somewhat simplifies the logic). The following clause verifies that only your value pairs are present on a doi_id:
What it does is count the number of records where the key pairs don’t match. If there are any, the comparison fails. You need to concateante your key value pairs for the in clause. Something like
in ('1,1', '2,2', '3,14').To generalize to the condition that all match, I use the following:
The
HAVINGclause first tests that all the pairs are present. The remaining clauses then test for the presence of each pair.There are other approaches. I find that the
HAVINGclause is the most general, because it can accommodate a wide range of logic on the inclusion criteria for the sets.