Given the three tables (Type, Value, and Links), here is another (crazy
looking) way to structure the query for the Person table.

SELECT P.*
FROM Person P
WHERE 
(
    EXISTS
    (
        SELECT null
        FROM StringLinks L
        JOIN StringValue SV ON L.ID = SV.ID AND SV.refTypeID = 1
        WHERE P.ID = L.parentID AND SV.f_val LIKE 'foo' 
    )
    OR 
    (
        NOT EXISTS
        ( 
            SELECT null
            FROM StringLinks L
            JOIN StringValue SV2 ON L.ID = SV.ID AND SV.refTypeID = 1
            WHERE P.ID = L.parentID AND SV.f_val LIKE 'foo'
        )
        AND
        EXISTS
        (
            SELECT null
            FROM StringType ST
            WHERE ST.ID = 1 AND ST.defaultVal LIKE 'foo'
        )
    )
)
AND 
(
    EXISTS
    (
        SELECT null
        FROM StringLinks L
        JOIN StringValue SV ON L.ID = SV.ID AND SV.refTypeID = 1
        WHERE P.ID = L.parentID AND SV.f_val LIKE 'bar' 
    )
    OR 
    (
        NOT EXISTS
        ( 
            SELECT null
            FROM StringLinks L
            JOIN StringValue SV2 ON L.ID = SV.ID AND SV.refTypeID = 1
            WHERE P.ID = L.parentID AND SV.f_val LIKE 'bar'
        )
        AND
        EXISTS
        (
            SELECT null
            FROM StringType ST
            WHERE ST.ID = 1 AND ST.defaultVal LIKE 'bar'
        )
    )
) 

-----Original Message-----
From: Robert DiFalco 
Sent: Friday, August 18, 2006 12:37 PM
To: Robert DiFalco; 'mysql@lists.mysql.com'
Subject: RE: More query help for user-defined values

No takers?
 

-----Original Message-----
From: Robert DiFalco
Sent: Thursday, August 17, 2006 3:03 PM
To: Robert DiFalco; mysql@lists.mysql.com
Subject: RE: More query help for user-defined values

One simple solution is to denormalize a little and take the refTypeID
column out of StringValue and add it to the Links table. Then I could
have:

    SELECT P.*
    FROM Person P

     LEFT JOIN StringLinks L1 ON P.ID = L1.parentID AND L1.refTypeID = 1
     LEFT JOIN StringValue SV1 ON L1.valueID = SV1.ID
     LEFT JOIN StringType  ST1 ON ST1.ID = 1

     LEFT JOIN StringLinks L2 ON P.ID = L2.parentID AND L2.refTypeID = 2
     LEFT JOIN StringValue SV2 ON L2.valueID = SV2.ID
     LEFT JOIN StringType  ST2 ON ST2.ID = 2

    WHERE ( SV1.f_val LIKE 'foo' OR
          ( SV1.val IS NULL AND ST1.defaultVal LIKE 'foo' ) )
      AND
          ( SV2.f_val LIKE 'bar' OR
          ( SV2.val IS NULL AND ST2.defaultVal LIKE 'bar' ) ) 


-----Original Message-----
From: Robert DiFalco [mailto:[EMAIL PROTECTED]
Sent: Thursday, August 17, 2006 8:43 AM
To: mysql@lists.mysql.com
Subject: More query help for user-defined values

To support user defined properties I have the following tables:

TABLE StringType
    LONG ID PKEY
    VARCHAR name
    ...
    VARCHAR defaultValue
    
TABLE StringValue
    LONG parentID
    LONG typeID
    VARCHAR val
    
Assume the correct indices are in place. Different string value types
can be defined by giving them a new row in StringType. The
StringValue.parentID can be a row from any table that has a LONG
identity column. If a row in the parent table does not have a
corresponding row in StringValue, we want to assume an implicit default
value.

So to return all the Person rows that have either an explicit
StringValue of ( type 1 and value foo ) or of ( type 2 and value bar ) I
can just execute the following query.

    SELECT P.*
    FROM Person P
     LEFT JOIN StringValue SV1 ON P.ID = SV1.parentID AND SV1.refTypeID
= 1
     LEFT JOIN StringType  ST1 ON ST1.ID = 1
     LEFT JOIN StringValue SV2 ON P.ID = SV2.parentID AND SV2.refTypeID
= 2
     LEFT JOIN StringType  ST2 ON ST2.ID = 2
    WHERE ( SV1.f_val LIKE 'foo' OR
          ( SV1.val IS NULL AND ST1.defaultVal LIKE 'foo' ) )
      AND
          ( SV2.f_val LIKE 'bar' OR
          ( SV2.val IS NULL AND ST2.defaultVal LIKE 'bar' ) )
          
The above seems to work fine. I can also get rid of the constant joins
on the type table and just do a subquery for the default value, either
approach works.

Now I want to change things to introduce a ValueLink table so that if
100 rows have the same string value that I don't have to write the
string 100 times. So my table structure changes like this:

TABLE StringType
    LONG ID PKEY
    VARCHAR name
    ...
    VARCHAR defaultValue
    
TABLE StringValue
    LONG ID PKEY  // the value unique ID
    LONG typeID
    VARCHAR val
    
TABLE StringLinks
    LONG parentID PKEY
    LONG valueID  PKEY
    
My naive approach to the query was this:

    SELECT P.*
    FROM Person P
     LEFT JOIN StringLinks L ON P.ID = L.parentID
     LEFT JOIN StringValue SV1 ON L.ID = SV1.ID AND SV1.refTypeID = 1
     LEFT JOIN StringType  ST1 ON ST1.ID = 1
     LEFT JOIN StringValue SV2 ON L.ID = SV2.ID AND SV2.refTypeID = 2
     LEFT JOIN StringType  ST2 ON ST2.ID = 2
    WHERE ( SV1.f_val LIKE 'foo' OR
          ( SV1.val IS NULL AND ST1.defaultVal LIKE 'foo' ) )
      AND
          ( SV2.f_val LIKE 'bar' OR
          ( SV2.val IS NULL AND ST2.defaultVal LIKE 'bar' ) )
          
As you can probably tell this wont work because the two values will now
show up in two different rows so the AND of the search terms will always
fail.

Can anyone think of a clean way to do this or do I have to get rid of
the joins altogether and do a subquery for each StringValue search term?

TIA,

R.





--
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:
http://lists.mysql.com/[EMAIL PROTECTED]




--
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to