Podzapytania w Propelu

17 lut
{lang: 'pl'}

Propel jest dla mnie wspaniałym ORM, który nieznacznie obniżając wydajność aplikacji bardzo korzystnie wpływa na późniejsze konserwowanie i udoskonalanie kodu. Wiele osób nie lubi propela zarzucając mu właśnie wspomniany przeze mnie spadek wydajności, albo ograniczone możliwości. Nie będę dywagował nad słusznością takich zarzutów, ponieważ w tym poście będzie o czym innym. W tym miejscu chciałbym pokazać jak w Propelu używać podzapytań używając do tego obiektu Criteria

Sortowanie po ilości wystąpień obiektu

Przypuśćmy, że w bazie znajduje się tabela Article oraz Comments. I teraz chciałbym pobrać wszystkie artykuły i posortować je zaczynając od tego, który ma najwięcej komentarzy i schodząc w dół. Jak to będzie wyglądać w surowym sql.

Z użyciem aliasu

SELECT article.title, article.body, COUNT( comment.comment_id ) AS nb_of_comments FROM article LEFT JOIN comment ON ( article.article_id=comment.article_id ) ORDER BY nb_of_comments DESC
$Criteria = new Criteria;
$Criteria->addAsColumn( 'nb_of_comments', sprintf( 'COUNT( %s )', CommentPeer::COMMENT_ID ) );
$Criteria->addJoin( ArticlePeer::ARTICLE_ID, CommentPeer::ARTICLE_ID, Criteria::LEFT_JOIN );
$Criteria->addDescendingOrderByColumn( 'nb_of_comments' );

Bez użycia aliasu

SELECT article.title, article.body FROM article LEFT JOIN comment ON ( article.article_id=comment.article_id ) ORDER BY COUNT( comment.comment_id ) DESC
$Criteria = new Criteria;
$Criteria->addJoin( ArticlePeer::ARTICLE_ID, CommentPeer::ARTICLE_ID, Criteria::LEFT_JOIN );
$Criteria->addDescendingOrderByColumn( sprintf( 'COUNT( %s )', CommentPeer::COMMENT_ID ) );

Jeden i drugi przykład zwróci wszystkie artykuły posortowane malejąco po ilości komentarzy. Jak widać sposób bez aliasu jest krótszy, ale sposób z aliasem niesie z sobą jedną korzyść- baza zwróci liczbę komentarzy. Co można z tym zrobić? A chociażby nadpisać metodę hydrate w obiekcie Article tak, żeby pakował liczbę komentarzy do składowej do której dostęp będzie wyglądał np. tak.

echo $Article->nb_of_comments;

Pozyskiwanie wyników wśród określonej puli obiektów

Przypuśmy, że nasza baza rozrosła się i chcielibyśmy pobrać rekordy w dość bardziej wyrafinowany sposób tak, żeby efekt jednego zapytania stanowił dane wejściowe służące do porównania w zapytaniu drugim. takie zapytanie może wyglądać następująco:

SELECT * FROM table_1 WHERE table_1.table_1_id IN ( SELECT  table_1.table_1_id FROM table_1 WHERE  table_1.created_at > 1232213321 )

Do generowania takich zapytań służy specjalny argument, który znaleźć można pod postacią stałej obiektu Criteria- mowa tutaj o CUSTOM. Sprawdźmy jak zapytanie może wyglądać w Propelu

$Criteria = new Criteria;

$subquery = sprintf( '%s IN ( SELECT %s FROM %s WHERE %s > %s )',
  Table1Peer::TABLE_1_ID,
  Table1Peer::TABLE_1_ID,
  Table1Peer::TABLE_NAME,
  Table1Peer::CREATED_AT,
  1232213321
 );

$Criteria->add( Table1Peer::TABLE_1_ID, $subquery, Criteria::CUSTOM );
...
Table1Peer::doSelect( $Criteria );

W tym przykładzie zrezygnowałem z jako takiej logiki ( ponieważ dane te można pobrać w o wiele bardziej optymalny sposób ), ale moim założeniem było przekazanie, jak łatwo można łączyć zapytania z użyciem obiektu Criteria z surowymi zapytaniami sql.

Mam nadzieję, że Sensio nie porzuci Propela na rzecz ( moim zdaniem przereklamowanego ) Doctrine i będzie go wspierać aż po wsze czasy ;)

Print Friendly

Wyszukiwane frazy:

  • propel podzapytania (2)
  • propel union (2)
  • addascolumn propel 1 5 (1)
  • propel union orm (1)
  • sql jak sprawdzić który artykuł ma najwięcej komentarzy (1)
  • symfony criteria addjoin (1)
  • symfony propel alias do kolumny (1)
  • symfony propel left join subquery (1)
  • tworzenie bazy propel (1)
  • union in propel (1)

Inne posty:

  1. ON UPDATE CURRENT_TIMESTAMP w Propelu
  2. Przydatne funkcje Symfony
  3. Jak wygenerować klauzulę IN
  4. Jak w MySQL posortować wyniki we własnym porządku

Tagi: , , , , ,

« »

[B]log programistyczny

IP 38.107.179.243 (38.107.179.243)