Search code examples
zend-frameworkzend-db-table

Zend Framework advanced WHERE IN query


So, i've come up with this query wich works perfectly fine when executed. However, since I want to use the pagination from Zend, the query has to be through an adapter.

This is the query that has to be converted: (i've cut the query so only the important part is here. I am aware of the fact that you can't run this query LOL)

//snip
WHERE
    city IN (
        SELECT 
            Plaatsnaam
        FROM
            plaatsnamen
        WHERE
            Latitude 
                BETWEEN 
                    ?
                AND 
                    ?
        AND
            Longitude
                BETWEEN
                    ?
                AND
                    ?       
    )
//snip

Works perfectly fine! However.. As you can see, i'm using an "advanced" WHERE IN case. Somehow, i can't get this converted and i'm stuck.

This is what it has to be converted to:

$db = Zend_Db_Table::getDefaultAdapter();                
$select = $db->select('gethousecity.id, city')
                                ->from('gethousecity')
                                    ->join('houses_props', 'houses_props.id = gethousecity.id')
                                ->where('city IN ()') // HOW TO CONVERT THE UPPER QUERY TO FIT IT HERE?
                                ->where('is_online = 1')
                                ->where('houses_props.prop_name = ?', 'something')
                                ->where('houses_props.prop_value BETWEEN ? AND ?', array(1,2));

I haven't found any documentation at all on how to convert the query into some format that fits here. Does anyone have any idea? Mostly because I need to insert some values and ZF is rewriting some weird shit there.

I'm kinda stuck now, any help would be awesome!


Solution

  • Subqueries work just fine.

    $select1->cols('id')->where('date > NOW()');
    $select2->where('id IN (?)', $select1);
    

    If the problem is the complex where, than you can use named parameters.

    $select1 = $db->select();
    $select2 = $db->select();
    $select1->from('plaatsnamen', array('Plaatsnaam'))
            ->where('Latitude BETWEEN :latmin AND :latmax')
            ->where('Longitude BETWEEN :longmin AND :longmax');
    $select2->from('gethousecity')
            ->join('houses_props', 'houses_props.id = gethousecity.id')
            ->where('city IN ?', $select1) // HOW TO CONVERT THE UPPER QUERY TO FIT IT HERE?
            ->where('is_online = 1')
            ->where('houses_props.prop_name = ?', 'something')
            ->where('houses_props.prop_value BETWEEN :propsmin AND :propsmax');
    die($select2);
    

    Returns:

    SELECT `gethousecity`.*, `houses_props`.*
    FROM `gethousecity`
    INNER JOIN `houses_props` ON houses_props.id = gethousecity.id
    WHERE 
        (city IN (
            SELECT `plaatsnamen`.`Plaatsnaam`
            FROM `plaatsnamen`
            WHERE 
            (Latitude BETWEEN :latmin AND :latmax) AND
            (Longitude BETWEEN :longmin AND :longmax)
        )) AND
        (is_online = 1) AND
        (houses_props.prop_name = 'something') AND
        (houses_props.prop_value BETWEEN :propsmin AND :propsmax)
    

    Which should work with named parameters, as seen in manual

    $bind = array(
        ':latmin' => 10,
        ':latmax' => 3,
        '...' => '...',
    );
    $db->fetchAll($select2, $bind);