Search code examples
mysqlsqlpostgresqlansi-sql

How to check if specific set of ID's exists?


I have a source table (piece of it):

+--------------------+
|  E M P L O Y E E   |
+--------------------+
| ID |   EQUIPMENT   |
+--------------------+
| 1  | tv,car,phone  |
| 2  | car,phone     |
| 3  | tv,phone      |
+----+---------------+

After normalization process I ended with two new tables:

+----------------+
| DICT_EQUIPMENT |
+----------------+
| ID | EQUIPMENT |
+----------------+
| 1  | tv        |
| 2  | car       |
| 3  | phone     |
+----+-----------+

+---------------------+
|    SET_EQUIPMENT    |
+----+--------+-------+
| ID | SET_ID | EQ_ID |
+----+--------+-------+
| 1  |   1    |   1   |
| 2  |   1    |   2   |
| 3  |   1    |   3   |
| 4  |   2    |   2   |
| 5  |   2    |   3   |
| 6  |   3    |   1   |
| 7  |   3    |   3   |
+----+--------+-------+

(the piece/part)
+-----------------+
| E M P L O Y E E |
+-----------------+
| ID | EQ_SET_ID  |
+-----------------+
| 1  |     1      |
| 2  |     2      |
| 3  |     3      |
+----+------------+

And now when I want to find correct SET_ID I can write something like this:

SELECT SET_ID
  FROM SET_EQUIPMENT S1,
       SET_EQUIPMENT S2,
       SET_EQUIPMENT S3
 WHERE S1.SET_ID = S2.SET_ID
   AND S2.SET_ID = S3.SET_ID
   AND S1.EQ_ID = 1
   AND S2.EQ_ID = 2
   AND S3.EQ_ID = 3;

Maybe any ideas for optimize this query? how find the correct set?


Solution

  • First, you should use explicit join syntax for the method you are using:

    SELECT S1.SET_ID
    FROM SET_EQUIPMENT S1 JOIN
         SET_EQUIPMENT S2
         ON S1.SET_ID = S2.SET_ID JOIN
         SET_EQUIPMENT S3
         ON S2.SET_ID = S3.SET_ID
     WHERE S1.EQ_ID = 1 AND
           S2.EQ_ID = 2 AND
           S3.EQ_ID = 3;
    

    Commas in a from clause are quite outdated. (And, this fixes a syntax error in your query.)

    An alternative method is to use group by with a having clause:

    SELECT S.SET_ID
    FROM SET_EQUIPMENT S
    GROUP BY S.SET_ID
    HAVING SUM(CASE WHEN S.EQ_ID = 1 THEN 1 ELSE 0 END) > 0 AND
           SUM(CASE WHEN S.EQ_ID = 2 THEN 1 ELSE 0 END) > 0 AND
           SUM(CASE WHEN S.EQ_ID = 3 THEN 1 ELSE 0 END) > 0;
    

    Which method works better depends on a number of factors -- for instance, the database engine you are using, the size of the tables, the indexes on the tables. You have to test which method works better on your system.