Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Elaborate Joins Query

I'm trying to solve the below problem.

I feel like it is possible, but I can't seem to get it.

Here's the scenario:

Table 1 (Assets)
1 Asset-A
2 Asset-B
3 Asset-C
4 Asset-D

Table 2 (Attributes)
1 Asset-A Red
2 Asset-A Hard
3 Asset-B Red
4 Asset-B Hard
5 Asset-B Heavy
6 Asset-C Blue
7 Asset-C Hard

If I am looking for something having the same attributes as Asset-A, then it should identify Asset-B since Asset-B has all the same attributes as Asset-A (it should discard heavy, since Asset-A didn't specify anything different or the similar). Also, if I wanted the attributes for only Asset-A AND Asset-B that were common, how would I get that?

Seems simple, but I can't nail it...

The actual table I am using, is almost precisely Table2, simply an association of an AssetId, and an AttributeId so: PK: Id
int: AssetId
int: AttributeId

I only included the idea of the asset table to simplify the question.

like image 526
Praesidium Avatar asked Oct 14 '22 14:10

Praesidium


1 Answers

SELECT  ato.id, ato.value
FROM    (
        SELECT  id
        FROM    assets a
        WHERE   NOT EXISTS
                (
                SELECT  NULL
                FROM    attributes ata
                LEFT  JOIN
                        attributes ato
                ON      ato.id = ata.id
                        AND ato.value = ata.value
                WHERE   ata.id = 1
                        AND ato.id IS NULL
                )
        ) ao
JOIN    attributes ato
ON      ato.id = ao.id
JOIN    attributes ata
ON      ata.id = 1
        AND ata.value = ato.value

, or in SQL Server 2005 (with sample data to check):

WITH    assets AS 
        (
        SELECT 1 AS id, 'A' AS name
        UNION ALL
        SELECT 2 AS id, 'B' AS name
        UNION ALL
        SELECT 3 AS id, 'C' AS name
        UNION ALL
        SELECT 4 AS id, 'D' AS name
        ),
        attributes AS
        (
        SELECT 1 AS id, 'Red' AS value
        UNION ALL
        SELECT 1 AS id, 'Hard' AS value
        UNION ALL
        SELECT 2 AS id, 'Red' AS value
        UNION ALL
        SELECT 2 AS id, 'Hard' AS value
        UNION ALL
        SELECT 2 AS id, 'Heavy' AS value
        UNION ALL
        SELECT 3 AS id, 'Blue' AS value
        UNION ALL
        SELECT 3 AS id, 'Hard' AS value
        )
SELECT  ato.id, ato.value
FROM    (
        SELECT  id
        FROM    assets a
        WHERE   a.id <> 1
                AND NOT EXISTS
                (
                SELECT  ata.value
                FROM    attributes ata
                WHERE   ata.id = 1
                EXCEPT
                SELECT  ato.value
                FROM    attributes ato
                WHERE   ato.id = a.id
                )
        ) ao
JOIN    attributes ato
ON      ato.id = ao.id
JOIN    attributes ata
ON      ata.id = 1
        AND ata.value = ato.value
like image 71
Quassnoi Avatar answered Oct 19 '22 22:10

Quassnoi