If not all ids are present return nothing

oracle

I have the following query

SELECT ATV.ATTRIBUTEVALUE_ID,
       ATV.ATTRIBUTE_ID,
       ASS.ASSET_ID
FROM   CLOTH.ATTRIBUTEVALUE ATV
JOIN   CLOTH.ASSET_ATTRIBUTEVALUE ASATV
ON     ATV.ATTRIBUTEVALUE_ID = ASATV.ATTRIBUTEVALUE_ID
JOIN   CLOTH.ASSET_ATTRIBUTE ASS_AT
ON     ASATV.ASSET_ATTRIBUTE_ID = ASS_AT.ASSET_ATTRIBUTE_ID
JOIN   CLOTH.ASSET ASS
ON     ASS.ASSET_ID = ASS_AT.ASSET_ID
WHERE  ATV.ATTRIBUTE_ID IN ( 1 , 2 , 3 ) 
AND    ASS.ASSET_ID IN ( 13057020, 9103354, 7829028 )

which returns

ATTRIBUTEVALUE_ID, ATTRIBUTE_ID, ASSET_ID,
7                      2          9103354
8                      2          7829028
9                      2          7829028
10                     2          7829028

It should return nothing, because 13057020 is not returned.

What this means is, when I have ATTRIBUTE_ID # and all ASSET_ID are not present (like now, 13057020 is missing) nothing should be returned.

Best Answer

One way:

WITH
  qry AS
  (  -- your query
    SELECT ATV.ATTRIBUTEVALUE_ID,
           ATV.ATTRIBUTE_ID,
           ASS.ASSET_ID
    FROM   CLOTH.ATTRIBUTEVALUE ATV
    JOIN   CLOTH.ASSET_ATTRIBUTEVALUE ASATV
    ON     ATV.ATTRIBUTEVALUE_ID = ASATV.ATTRIBUTEVALUE_ID
    JOIN   CLOTH.ASSET_ATTRIBUTE ASS_AT
    ON     ASATV.ASSET_ATTRIBUTE_ID = ASS_AT.ASSET_ATTRIBUTE_ID
    JOIN   CLOTH.ASSET ASS
    ON     ASS.ASSET_ID = ASS_AT.ASSET_ID
    WHERE  ATV.ATTRIBUTE_ID IN ( 1 , 2 , 3 ) 
    AND    ASS.ASSET_ID IN ( 13057020, 9103354, 7829028 )
  ),
  cnt AS
  ( -- count condition to be satisfied
    SELECT 1
    FROM qry
    HAVING COUNT(DISTINCT ASSET_ID) = 3
  )
SELECT qry.*
FROM qry, cnt ;

The cnt will have 0 rows and so will the cross join (FROM qry, cnt) if the condition is not met.

You could write the final query like this, perhaps it's more readable:

WITH
---

  cnt AS
  ( -- count condition to be satisfied
    SELECT COUNT(DISTINCT ASSET_ID) AS assets
    FROM qry
  )
SELECT qry.*
FROM qry
WHERE (SELECT assets FROM cnt) = 3 ;

Another way would be a window function:

WITH
  qry AS
  (  -- your query with one more column
    SELECT ATV.ATTRIBUTEVALUE_ID,
           ATV.ATTRIBUTE_ID,
           ASS.ASSET_ID,
           COUNT(DISTINCT ASS.ASSET_ID) OVER () AS assets
    FROM   CLOTH.ATTRIBUTEVALUE ATV
    JOIN   CLOTH.ASSET_ATTRIBUTEVALUE ASATV
    ON     ATV.ATTRIBUTEVALUE_ID = ASATV.ATTRIBUTEVALUE_ID
    JOIN   CLOTH.ASSET_ATTRIBUTE ASS_AT
    ON     ASATV.ASSET_ATTRIBUTE_ID = ASS_AT.ASSET_ATTRIBUTE_ID
    JOIN   CLOTH.ASSET ASS
    ON     ASS.ASSET_ID = ASS_AT.ASSET_ID
    WHERE  ATV.ATTRIBUTE_ID IN ( 1 , 2 , 3 ) 
    AND    ASS.ASSET_ID IN ( 13057020, 9103354, 7829028 )
  )
SELECT qry.ATTRIBUTEVALUE_ID,
       qry.ATTRIBUTE_ID,
       qry.ASSET_ID
FROM qry
WHERE qry.assets = 3 ;