AND nad více výběrů z podtabulek

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
pcs
Člen | 22
+
0
-

Pro jednoduchost používám příklad uvedený v dokumentaci:

Potřebuji napsat něco, co mi vybere záznamy tabulky book, které mají tag_id například 1 i 2.

<?php
$rows = $book->where('id',$book_tag->select('book_id')->where('tag_id',array(1,2)));
?>

Tohle mi vybere všechny záznamy, které mají tag 1 NEBO 2.
Jak mám vybrat pouze záznamy, které mají tag 1 A 2?
Výsledek by asi měl vypadat nějak takto:

SELECT * FROM book WHERE book.id IN (SELECT book_id FROM book_tag WHERE tag_id = 1) AND book.id IN (SELECT book_id FROM book_tag WHERE tag_id = 2)
JakubTN
Bronze Partner | 49
+
0
-

Skusil by som taketo nieco:

<?php
$rows = $book->where('id',$book_tag->select('book_id')->where('tag_id',1)->where('tag_id',2));
?>

Pripadne niektoru z variant na tejto stranke

Editoval JakubTN (1. 8. 2012 9:33)

jtousek
Člen | 951
+
0
-

@JakubTN: To nemůže fungovat… Tady budou potřeba poddotazy. Vím jak to napsat v SQL, ale nevím jak to napsat v NDB.

Editoval jtousek (1. 8. 2012 9:37)

petr.pavel
Člen | 535
+
0
-

JakubTN má pravdu, poddotazy používat můžeš.

uestla
Backer | 799
+
0
-

Nespojujte NDB automaticky se Table\Selection. NDB je obálka nad PDO, takže tebou uvedený dotaz (na který se Table\Selection evidentně nehodí) můžeš normálně zapsat…

$connection->query( ... );
petr.pavel
Člen | 535
+
0
-

Nevím, proč by se uvedený dotaz neměl hodit na Table\Selection, nicméně jak tak na něj koukám, asi je nesmyslný:

SELECT * FROM book WHERE book.id IN (seznam1) AND book.id IN (seznam2)

Jak by mohlo být id současně v jednom seznamu i v druhém? Jedině pokud se seznam1 a seznam2 překrývají. Pak ale můžeš rovnou oba seznamy sloučit a ptát se jen:

SELECT * FROM book WHERE book.id IN (SELECT book_id FROM book_tag WHERE tag_id IN (1,2))

Na což se přesně hodí PHP kód, který jsi (@pcs) sám uvedl v úvodním postu:

<?php
$rows = $book->where('id',$book_tag->select('book_id')->where('tag_id',array(1,2)));
?>

Editoval petr.pavel (1. 8. 2012 11:46)

jtousek
Člen | 951
+
0
-

@petr.pavel: Jenže tím dostaneš knihy, které mají tag 1 nebo tag 2. Cíl je vybrat jen ty knihy, které mají oba dva tagy.

pcs
Člen | 22
+
0
-

Melmen napsal(a):

http://sql-cross-queries.freexit.eu/nettedb#3 ?

To je úplně o něčem jiném. Ty vybíráš z tabulky column1 = value1 AND column2 = value2.

Já potřebuji vybrat záznamy, které mají pro stejnou hodnotu column1 hodnoty column2 = value1 AND column2 = value2

petr.pavel
Člen | 535
+
0
-

sql-cross-queries: Nevím, proč by to mělo být jiné, tohle je univerzální návod. Napsat column2 místo column1 na tom nic nemění.

@jtousek: Safra, máš recht, jsem pako. I tak bych ale radši nepokládal dva pod-dotazy, ale jeden. Šlo by tohle?

SELECT * FROM book WHERE book.id IN (
  SELECT book_id FROM book_tag WHERE tag_id IN (1,2) HAVING COUNT(DISTINCT tag_id) = 2
)
jtousek
Člen | 951
+
0
-

@petr.pavel: Jo, tohle už by šlo. :) Jen mám pocit že HAVING nelze použít bez GROUP BY, takže bych ještě přidal GROUP BY tag_id.

petr.pavel
Člen | 535
+
0
-

@jtousek: Asi's myslel GROUP BY book_id ;-)

jtousek
Člen | 951
+
0
-

@petr.pavel: Samozřejmě. :-D Ale dohromady jsme to nakonec dali, ne? :-P

pcs
Člen | 22
+
0
-

Kluci díky, jste dobří. Odzkoušel jsem to a funguje to. Jen to ještě přepíšu pro další případné zájemce, protože asi nebudu jediný, kdo tohle potřebuje použít.

SELECT * FROM book WHERE book.id IN (
  SELECT book_id FROM book_tag WHERE tag_id IN (1,2)
  GROUP BY book_id HAVING COUNT(DISTINCT tag_id) = 2
)