2011-01-10 15 views
6

Dlaczego doktryna (1.2) używa WHERE IN zamiast LIMIT?Dlaczego doktryna używa GDZIE IN zamiast LIMITU?

ten kod:

Doctrine_Query::create() 
    ->from('Table t') 
    ->limit(10) 
    ->getSqlQuery(); 

Zwraca coś takiego:

SELECT t.id_table AS t__id_table FROM table AS t WHERE t__id_table IN (1,2,3,4,10,12,18,20,21,25); 

Zamiast tego:

SELECT t.id_table AS t__id_table FROM table AS t LIMIT 10; 

Ten behaivor jest taka sama dla każdej wartości LIMIT. Generuje to bardzo długie zapytania dla wysokich wartości LIMIT.

Dodatkowe pytanie: w jaki sposób Doctrine wie, jakich identyfikatorów można użyć? (Wysyłając kolejne zapytanie do DB?)

+0

Jakiego zaplecza bazy danych używasz? –

+0

@Matt Gibson: MySQL –

+0

Nieparzysty; Właśnie zrobiłem coś podobnego z Doctrine z Symfony 1.4, które ja _think_ jest w wersji 1.2.3 i używa klauzuli LIMIT dla MySQL, jak można się spodziewać. –

Odpowiedz

4

Dzieje się tak, ponieważ LIMIT działa na wierszach baz danych, a nie "obiektach". Po wpisaniu $q->limit(10) chcesz uzyskać dziesięć obiektów, a nie dziesięć wierszy z bazy danych.

Rozważmy następującą kwerendę (produkty i kategorie mają wiele do wielu relacji):

SELECT p.*, c.* FROM product p 
INNER JOIN product_category_ref pcr ON p.id = pcr.prodcut_id 
INNER JOIN category c ON c.id = pcr.category_id 
WHERE p.price < 123; 

Aby pobierać produkty (10 obiektów) zapytanie będzie musiał pobrać co najmniej 20 wierszy. Nie możesz użyć LIMIT 10 powodu (na przykład) tylko 3 produkty zostaną zwrócone. Dlatego musisz dowiedzieć się, które produkty powinny zostać pobrane (limit dotyczy produktów), a następnie pobrać aktualne dane.

To spowoduje następujące pytania:

SELECT p.id FROM product p WHERE p.price < 123; 
SELECT ..... WHERE p.id IN (...); 

drugie zapytanie może zwrócić 20, 423 lub 31 wierszy. Jak widać, nie jest to wartość od limit().

PS. Doctrine2 jest w tym przypadku znacznie bardziej przejrzysta, ponieważ używa metody setMaxResults(), zamiast niejszej, co jest mniej kłopotliwe.

+0

Skąd masz tę informację? zgodnie z limitem manualnym() jest częścią DQL i jest używany przed nawodnieniem –

+0

Wiem, że z własnego doświadczenia i badania źródeł. I tak, masz rację - "LIMIT" jest częścią DQL (metoda 'limit()' pochodzi z 'QueryBuilder') i jak widzisz jest używana przed uwadnianiem (druga kwerenda (ta, która jest faktycznie uwodniona) doesn 'nawet ma klauzulę 'LIMIT')). – Crozin

+0

To brzmi dla mnie dziwnie. Ja (i moi koledzy) myśleli, że LIMIT stosuje się do liczby wierszy zwracanych przez zapytanie (po przetworzeniu wszystkich sprzężeń, podzapytań itp.). –

0

Korzystanie Doctrine 1.2.3:

<?php 

include(dirname(__FILE__).'/Doctrine.php'); 
spl_autoload_register(array('Doctrine', 'autoload')); 

$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'testdb', 'testdb'); 
$conn = Doctrine_Manager::connection($dbh); 

class Table extends Doctrine_Record { 
    public function setTableDefinition() { 
    $this->hasColumn('id_table', integer, 10, array('primary' => true)); 
    } 
} 

$q = Doctrine_Query::create() 
    ->from('Table t') 
    ->limit(10) 
    ->getSqlQuery(); 

echo $q; 

uzyskać wynik:

SELECT t.id_table AS t__id_table FROM table t LIMIT 10 

Czy jest może coś innego dzieje się w kodzie?

+0

Właśnie dowiedzieliśmy się, że GDZIE IN jest używane tylko podczas korzystania z JOIN. Przepraszam za nieporozumienie. –

Powiązane problemy