2012-05-14 1 views
1

Итак, я придумал этот запрос, который отлично работает при выполнении. Однако, поскольку я хочу использовать разбиение на страницы из Zend, запрос должен быть через адаптер.Zend Framework advanced WHERE IN query

Это запрос, который должен быть преобразован: (. Я уже перерезал запрос таким образом, только важная часть здесь я отдаю себе отчет в том, что вы не можете запустить этот запрос LOL)

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

Работает отлично! Однако .. Как вы можете видеть, я использую «продвинутый» WHERE IN case. Так или иначе, я не могу заставить это преобразовать, и я застрял.

Это то, что он должен быть преобразован в:

$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)); 

Я не нашел никаких документов вообще о том, как преобразовать запрос в какой-то формат, который подходит здесь. Кто-нибудь есть идеи? В основном потому, что мне нужно вставить некоторые значения, а ZF переписывает какое-то странное дерьмо.

Я сейчас застрял, любая помощь была бы потрясающей!

ответ

3

подзапросов работать нормально.

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

Если проблема - это комплекс, где вы можете использовать именованные параметры.

$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); 

Возвращает:

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) 

, который должен работать с именованными параметрами, как показано на manual

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

Да, для этих простых вопросов есть. Не когда у вас есть подзапрос. – ChrisH

+0

См. Мой обновленный ответ :) –

+0

Еще более обновленный :) –

0

Насколько я знаю, ZF DB не имеет встроенной поддержки подзапросов.

Вы могли бы попытаться сделать это:

// snip 
->where("city IN (
    SELECT Plaatsnaam 
    FROM plaatsnamen 
    WHERE Latitude BETWEEN $lowLat AND $highLat 
     AND Longitude BETWEEN $lowLon AND $highLon 
)") 
// snip 

EDIT: Интерполяция значения непосредственно в строке условий, это безопасно, только если переменные являются доверенными (или, если вы получили их от пользователя, убедитесь, что вы бросаете их на плавательные элементы, прежде чем делать это).

В качестве альтернативы вы можете попытаться избежать подзапроса, а вместо этого присоединиться к объединению, но это может иметь последствия для производительности (возможно, к лучшему или к худшему).

+0

Ну, я подумал о том, что, как хорошо. Однако это не работает.ZF перезаписывает запрос таким странным образом: http://pastebin.com/veCSzj6A – ChrisH

+0

@SiteSafeNL Можете ли вы разместить результирующий запрос? –

+0

Да, URL не вставлял ха-ха; http://pastebin.com/veCSzj6A – ChrisH

0

В конце концов, в качестве быстрого обходного пути я придумал следующее; $ Db-> цитата.

$select = $db->select('gethousecity.id, city') 
            ->from('gethousecity') 
             ->join('houses_props', 'houses_props.id = gethousecity.id') 
            ->where('city IN ( 
                SELECT Plaatsnaam 
                FROM plaatsnamen 
                WHERE Latitude BETWEEN '.$latlon_search[0].' AND '.$latlon_search[1].' 
                 AND Longitude BETWEEN '.$latlon_search[2].' AND '.$latlon_search[3].' 
            )') 
            ->where('is_online = 1') 
            ->where('houses_props.prop_name = ?', 'vraagprijs[vraagprijs]') 
            ->where('houses_props.prop_value BETWEEN '.$db->quote($price_start).' AND '.$db->quote($price_end)); 

Для меня это был единственный способ сделать эту работу. Каждый раз, когда я сделал:

->where('statement ? AND ?', array($val1, $val2) 

Результат был таков:

statement val1,val2 AND val1,val2 
0

Попробуйте это

$db = Zend_Db_Table::getDefaultAdapter(); 
    $selectInner = $db->select()->from('plaatsnamen','Plaatsnaam') 
        ->where("Lattitude BETWEEN $lowLat AND $highLat") 
        ->where("Longitude BETWEEN $lowLon AND $highLon") 
        ->__toString(); 



    $select = $db->select('gethousecity.id, city') 
            ->from('gethousecity') 
             ->join('houses_props', 'houses_props.id = gethousecity.id') 
            ->where("city IN ($selectInner)"); 
+0

Вы должны определенно процитировать варсы по вопросам безопасности. – ChrisH