Question

I have a table with a many-to-many relationship to two other tables:

CREATE TABLE assoc (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  ref1 INT NOT NULL,
  ref2 INT NOT NULL,
  INDEX composite_key (ref1, ref2)
);

I want to determine if there are associations with ref1 that match and do not match a given value for ref2. As an example, lets say I'd like to match if an association for ref1 is present with a value of 1000 and any other value for ref2:

INSERT INTO assoc (ref1, ref2) VALUES
  (100, 10),
  (100, 1000);

However, no match should be given if only the value 1000 is associated with ref1, or if it is solely any other value:

INSERT INTO assoc (ref1,ref2) VALUES
  (101, 10),
  (102, 1000);

I came up with two solutions. 1) Create a temp table with the results of rows that do match the value, then SELECT from that the rows that do not match the value, and 2) join the same table, and specify the not matching criteria from that table.

CREATE TEMPORARY TABLE set
  SELECT ref1 FROM assoc
  WHERE ref2 = 1000;
SELECT assoc.ref1 FROM `set`
  JOIN assoc ON `set`.ref1 = assoc.ref1
  WHERE assoc.ref2 <> 1000;

SELECT assoc.ref1 FROM assoc 
  JOIN assoc AS `set` ON assoc.ref1 = `set`.ref1
  WHERE assoc.ref2 = 1000 AND `set`.ref2 <> 1000;

However, I'd like to know if there are other ways to accomplish this match?

Was it helpful?

Solution

I think your second solution is the standard way to do what you want; I'd do it the same way. You have also added the INDEX composite_key correctly. However, you might add an additional GROUP BY to avoid that the same assoc.ref1 appears as many times as the join finds associated rows with ref2 <> 1000:

SELECT assoc.ref1 FROM assoc 
  JOIN assoc AS `set` ON assoc.ref1 = `set`.ref1
  WHERE assoc.ref2 = 1000 AND `set`.ref2 <> 1000
  GROUP BY assoc.ref1;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top