2009-09-24 1 views
5

Ok, ecco la situazione, ho un'applicazione scritta in Zend_Framework, che è compatibile con MySQL e MSSQL come backend. Ora, ZF è abbastanza bravo a risolvere molte discrepanze/differenze SQL tra le due lingue, ma devo ancora capirlo.Zend_Db_Seleziona l'ordine in ordine casuale, compatibile in mssql/mysql

L'obiettivo è selezionare 1 record casuale dalla tabella, che è un'affermazione estremamente semplice.

Ecco una dichiarazione prescelta ad esempio:

$sql = $db->select() 
     ->from("table") 
     ->order("rand()") 
     ->limit(1); 

Questo funziona perfettamente per le tabelle del database MySQL, perché lo SQL per MySQL è la seguente:

SELECT `table`.* FROM `table` ORDER BY rand() ASC 

Ora MSSQL d'altra parte, usa la funzione newid() per fare randomizzazione.

Esiste una sorta di aiuto che posso passare alla funzione order() per far sì che si accorga che deve utilizzare l'ordinamento corretto? Ho cercato la documentazione e gli zfforum, ho trovato alcuni suggerimenti, ma nulla di solido.

Una delle cose che ho trovato era:

ORDER BY RANDOM() not working - ZFForums.com

Stanno usando la seguente:

$res = $db->fetchAll(
'SELECT * FROM table ORDER BY :random', 
array('random' => new Zend_Db_Expr('RANDOM()') 
); 

Funziona ... ma io non sto cercando di costruisco la mia istruzione select digitandola e facendo una sostituzione sulla stringa, sto cercando di mantenerla nello stesso oggetto Zend_Db_Select. Ho anche provato a passare il Zend_Db_Expr('RANDOM()') nel ->order() sull'istruzione e fallisce. Inserisce anche una soluzione teorica per trovare la risposta, ma non sto cercando di riscrivere la funzione all'interno, modificando la chiamata $ db-> fetch().

Qualche idea?

risposta

14

Si potrebbe rapidamente estratto la funzione di un tavolo - chi lo sa quale scheda che sta usando:

class MyTable extends Zend_Db_Table_Abstract { 
    public function randomSelect($select=null) { 
    if ($select === null) $select = $this->select(); 
    if (!$select instanceOf Zend_Db_Select) $select = $this->select($select); 
    $adapter = $this->getAdapter(); 
    if ($adapter instanceOf Zend_Db_Adapter_Mysqli) { 
     $select->order(new Zend_Db_Expr('RAND()')); 
    } else if ($adapter instanceOf Zend_Db_Adapter_Dblib) { 
     $select->order(new Zend_Db_Expr('NEWID()')); 
    } else { 
     throw new Exception('Unknown adapter in MyTable'); 
    } 
    return $select; 
    } 
} 

$someSelect = $table->select(); 
// add it to an existing select 
$table->randomSelect($someSelect); 

// or create one from scratch 
$select = $table->randomSelect(); 

Inoltre, ho trovato un articolo da qualche parte che ho perso che consiglia di provare qualcosa di simile:

$select->order(new Zend_Db_Expr('0*`id`+RAND())); 

per sovvertire il Query Optimizer di MSSQL e ingannarlo per calcolare un nuovo valore per ogni riga.

2

Vorrei creare la classe My_Db_Expr_Rand estende Zend_Db_Expr. Con un basso sull'adattatore, restituirei l'uno o l'altro.

+0

Mi piace, ma penso che mi piaccia un po 'di più l'idea di gnarf. L'estensione dell'estratto di una tabella per una scelta casuale funziona alla grande. – Jesta

+0

Sì, certo. La mia soluzione è più complessa e deriva dalla cosa che si desidera creare ** UN'ESPRESSIONE ** basata su un adattatore. Quindi è generalmente riutilizzabile per qualsiasi altro progetto ... Ma sono d'accordo sul fatto che la soluzione da tavolo sia più semplice ... –

+0

In fondo ha anche mostrato il Db_Expr che puoi usare per MSSQL e MySQL senza doverlo modificare, lasciandolo generalmente riutilizzabile anche per qualsiasi progetto. – Jesta