Jaki jest właściwy sposób napisania zapytania zawierającego „NOT IN” przy użyciu instrukcji warunku?
Moje zapytanie jest następujące:
SELECT DISTINCT nid FROM node WHERE language NOT IN
(SELECT language
FROM languages WHERE language = 'ab');
Próbowałem czegoś takiego:
$query->condition('n.' . $key, $value, 'not in (select language from
languages where language = $value)');
SELECT nid FROM node WHERE language != 'ab'
?Odpowiedzi:
W konkretnym przykładzie powinieneś po prostu napisać warunek jako:
W ogólnym przypadku, w którym należy wybrać wiersze w bazie danych na podstawie wartości zwróconych z zapytania częściowego, należy rozważyć następujące kwestie:
„NOT IN” jest akceptowane jako operator od
SelectQuery::condition()
. W rzeczywistości zostanie wykonane następujące zapytanie:Jak podano w klauzulach warunkowych („Subselects”),
SelectQuery::condition()
akceptuje również obiekt implementującySelectQueryInterface
jako wartość$value
, taki jak ten zwracany przezdb_select()
; problem polega na tym, że właściwie można go użyć, gdy wartość$operator
jest równa"IN"
. Zobacz: Podselekty nie działają w warunkach DBTNG, z wyjątkiem przypadków użycia jako wartości IN .Jedyny sposób, w jaki widzę użycie operatora „NOT IN” w zapytaniu podrzędnym
condition
to:Wykonaj główne zapytanie, ustawiając warunek jak w poniższym fragmencie
$subquery_result
to tablica zawierająca wynik zapytania podrzędnego.W przeciwnym razie możesz użyć,
where()
jak powiedzieli inni, który akceptuje ciąg dla części zapytania, którą musisz dodać.Pamiętaj, że
db_select()
jest to wolniejszedb_query()
; powinieneś użyć pierwszego, gdy wiesz, że zapytanie może zostać zmienione przez inne moduły. W przeciwnym razie, jeśli inne moduły nie powinny używaćhook_query_alter()
do zmiany zapytania, należy użyćdb_query()
.W przypadku uzyskiwania dostępu do węzłów, jeśli potrzebujesz uzyskać tylko te węzły, do których użytkownik ma dostęp, musisz użyć
db_select()
i dodać'node_access'
jako znacznik zapytania za pomocąSelectQuery::addTag()
. Na przykładblog_page_last()
używa następującego kodu.Podobny kod jest używany przez
book_block_view()
.źródło
Pisząc złożone zapytania, zdecydowanie powinieneś użyć
db_query()
zamiastdb_select()
.NOT IN
klauzuli z podzapytaniem z bieżącym interfejsem API bazy danych Drupal (jest to znany problem w trakcie opracowywania).db_select()
.db_query()
.Jeśli chodzi o zapytanie, nie jestem pewien, dlaczego chcesz użyć podzapytania (chyba że uprościłeś swój przykład)? Możesz to łatwo napisać w ten sposób:
DISTINCT
nie jest konieczne, ponieważnid
jest kluczem podstawowym, więc nie będzie duplikowane.źródło
Istnieje również where (), które pozwala dodać dowolny warunek where do zapytania.
Przykład:
Jak wspomniano w keithm, musisz wybrać db_select () i addTag ('node_access') podczas wybierania węzłów, które są następnie wyświetlane użytkownikom.
źródło
Łatwiejszym sposobem użycia db_select z podseleksem NOT IN jest po prostu użycie mało znanego
$ zapytanie-> gdzie
dodać dowolny warunek where.
na przykład:
źródło
Gdzie $ subquery_values jest tablicą formatu $ key => $ nid w wyniku podzapytania
to działa dobrze.
źródło