[Dbix-class] Re: how to use a complex query in DBIx::Class

A. Pagaltzis pagaltzis at gmx.de
Sat Dec 30 08:59:18 GMT 2006


* Matt LeBlanc <mleblanc at cpan.org> [2006-12-30 08:10]:
> Sorry, I just realized I used the wrong field. Of course, this
> doesn't matter as if the join condition fails, anything from
> hiddenboards is null. Here is a full example of how this would
> work:
> 
> CREATE TABLE boards (
> 	id int,
> 	active int,
> 	pos int
> );
> 
> INSERT INTO boards VALUES(1,1,1);
> INSERT INTO boards VALUES(2,1,2);
> INSERT INTO boards VALUES(3,1,3);
> 
> CREATE TABLE hiddenboards (
> 	userid int,
> 	boardId int	
> );
> 
> INSERT INTO hiddenboards VALUES(1,1); -- not userid 3, so no join
> INSERT INTO hiddenboards VALUES(3,2); -- userid 3, so valid join
> -- no entry for id 3 so no join
> 
> SELECT boards.id,CASE WHEN hiddenboards.userid is not null THEN 1 ELSE 0 END AS hidden
> FROM boards LEFT JOIN hiddenboards
> ON hiddenboards.userid = 3
> AND hiddenboards.boardid = boards.id
> WHERE boards.active = 1
> ORDER BY pos;
> 
> In this particular case, the rows returned are as follows:
> 
> id,hidden
> 1,0
> 2,1
> 3,0

You’re abusing the ON clause. You’re not joining on the userid
condition; you’re constraing the result set. You should put it in
the WHERE clause:

    SELECT
        b.id,
        CASE WHEN h.userid IS NOT NULL THEN 1 ELSE 0 END AS hidden
    FROM boards b
    LEFT JOIN hiddenboards h ON h.boardid = b.id
    WHERE
        b.active = 1
        AND h.userid = 3
    ORDER BY b.pos

But this is really an abuse of joining, because you’re not
actually interested in joining data, only in checking, which
should be written as a correlated subquery:

    SELECT
        b.id,
        EXISTS (
            SELECT NULL
            FROM hiddenboards h
            WHERE
                h.userid = 3
                AND h.boardid = b.id
        ) AS hidden
    FROM boards b
    WHERE b.active = 1
    ORDER BY b.pos

Note that I use EXISTS and select nothing but NULL to make it
clear that the only fact of interest is whether a matching row
exists in `hiddenboards`.

In that way it is self-documenting what you’re trying to ask for.

Regards,
-- 
Aristotle Pagaltzis // <http://plasmasturm.org/>



More information about the Dbix-class mailing list