チェックする複雑なWHEREクエリを作成します。
If(条件1 = TRUE)AND(条件2 = TRUE)AND(条件3 = TRUE OR条件4 = TRUE)
したがって、最初の2つの条件は常にtrueでなければならず、次に条件3または4のいずれかがtrueでなければなりません。
私はコードで試しています:
->select ($db->quoteName(array('c.event','b.date','b.type','a.mob','a.joined','a.left')))
->from ($db->quoteName('app_mob_animal', 'a'))
->join('INNER', $db->quoteName('app_event_animal', 'b') . 'ON (' .$db->quoteName('a.mob'). '=' .$db->quoteName('b.mob').')')
->join('INNER', $db->quoteName('app_events', 'c') . 'ON (' .$db->quoteName('b.event'). '=' .$db->quoteName('c.id').')')
->join('INNER', $db->quoteName('app_mob', 'd') . 'ON (' .$db->quoteName('a.mob'). '=' .$db->quoteName('d.id').')')
->where (($db->quoteName('a.animal') . 'LIKE' . $db->quote($anid)), 'AND')
->where (($db->quoteName('a.joined') . '<=' . $db->quoteName('b.date')), 'AND')
->where (($db->quoteName('a.left') . '>=' . $db->quoteName('b.date') .'OR'. ($db->quoteName('a.left') .'LIKE'. $db->quote($emptyDate))));
しかし、自分の応答を吐き出すと、2番目の条件を明確に破る結果が得られます。これは私の結果を除いてです、2番目の結果は基準を満たしていません。
[0]=>
object(stdClass)#891 (6) {
["event"]=>
string(7) "weighed"
["date"]=>
string(19) "2015-04-19 00:00:00"
["type"]=>
string(3) "mob"
["mob"]=>
string(2) "11"
["joined"]=>
string(19) "2015-04-18 11:39:14"
["left"]=>
string(19) "0000-00-00 00:00:00"
}
[1]=>
object(stdClass)#888 (6) {
["event"]=>
string(9) "vet visit"
["date"]=>
string(19) "2015-03-31 11:46:08"
["type"]=>
string(3) "mob"
["mob"]=>
string(2) "11"
["joined"]=>
string(19) "2015-04-18 11:39:14"
["left"]=>
string(19) "0000-00-00 00:00:00"
}
このクエリのWHERE部分の正しい構文は何ですか?
あなたのOR
状態はそれを壊しています。今はそうです。
if condition1 = TRUE AND condition2 = TRUE AND condition3 = TRUE OR condition4 = TRUE
だからあなたは()
条件3と4の周り。これにより、condition4
はtrue
です。
やってみる
->select ($db->quoteName(array('c.event','b.date','b.type','a.mob','a.joined','a.left')))
->from ($db->quoteName('app_mob_animal', 'a'))
->join('INNER', $db->quoteName('app_event_animal', 'b') . ' ON (' .$db->quoteName('a.mob'). '=' .$db->quoteName('b.mob').')')
->join('INNER', $db->quoteName('app_events', 'c') . ' ON (' .$db->quoteName('b.event'). '=' .$db->quoteName('c.id').')')
->join('INNER', $db->quoteName('app_mob', 'd') . ' ON (' .$db->quoteName('a.mob'). '=' .$db->quoteName('d.id').')')
->where ($db->quoteName('a.animal') . ' LIKE ' . $db->quote($anid), 'AND')
->where ($db->quoteName('a.joined') . '<=' . $db->quoteName('b.date'), 'AND')
->where ('('.$db->quoteName('a.left') . '>=' . $db->quoteName('b.date') .' OR '. $db->quoteName('a.left') .' LIKE '. $db->quote($emptyDate).')');
クエリを印刷して、どのように構築されているかを確認できます。
たとえば、クエリ変数が$query
、次に行います
echo $query->dump(); // Thanks to @DmitryRekun
そして、それは実行されるものすべてのクエリを出力します。このようにして、何が問題なのかを確認できます。単純なデバッグ用です。
実用的なソリューションが受け入れられた後で投稿したいという衝動を抑えるつもりでしたが、コードの可読性、意図、簡潔さ、および(目立たない程度に)改善するためにクエリ構築プロセスを変更する方法を説明することに価値があると後で決めましたセキュリティ/機能を維持しながらパフォーマンス。また、個人的なコーディングの好みの問題にすぎないいくつかの提案についても説明します。私は事前に、ルネの答えは安全で完全に機能していると言いたいだけです。
クエリをコード化する方法とその理由を次に示します。
$anid = "animal's string"; // hypothetical
$emptyDate = "2018-06-21"; // hypothetical
$db = JFactory::getDBO();
try {
$query = $db->getQuery(true)
->select(
array(
"c.event",
"b.date",
"b.type",
"a.mob",
"a.joined",
$db->qn("a.left")
)
)
->from("app_mob_animal a")
->innerJoin("app_event_animal b ON a.mob = b.mob")
->innerJoin("app_events c ON b.event = c.id")
->innerJoin("app_mob d ON a.mob = d.id")
->where(
array(
"a.joined <= b.date",
"a.animal = " . $db->q($anid)
)
)
->andWhere(
array(
$db->qn("a.left") . " >= b.date",
$db->qn("a.left") . " = " . $db->q($emptyDate)
),
"OR"
);
echo $query->dump();
$db->setQuery($query);
if (!$result = $db->loadAssocList()) { // declare variable and check for empty array
echo "<div>No Qualifying Rows</div>";
} else {
foreach ($result as $row) {
// ... do what you like with $row['event'] etc. (table names/alias are omitted from the resultset keys)
}
}
} catch (Exception $e) {
echo "<div>Syntax error, please contact the developer</div>";
// echo $e->getMessage(); // <-- not to be displayed publicly
}
これは、目的のクエリロジックを提供するレンダリングされたクエリ(->dump()
から)です。
SELECT c.event、b.date、b.type、a.mob、a.joined、 `a`.`left`
FROM app_mob_animal a
INNER JOIN app_event_animal b ON a.mob = b.mob
INNER JOIN app_events c ON b.event = c.id
INNER JOIN app_mob d ON a.mob = d.id
どこ
(a.joined <= b.date AND a.animal = 'animal \' s string ')AND
( `a`.`left`> = b.date OR` a`.`left` = '2018-06-19')
説明:
SELECT
句の列は配列形式ですが、カンマ区切り値の単一の文字列と同じように簡単に書き込むことができます。 left
列名のみ[〜#〜] [〜#〜]をバックティックラップする必要があります-これは、ハードコードされたバックティックまたはqn()
呼び出し。left
は予約語です。 event
、date
、およびtype
はMySQLキーワードですが、予約されていません。 IMO、メリットのない関数呼び出しを排除することは、良いコーディング習慣です。qn()
の省略形としてquoteName()
を使用しています。q()
の場合はquote()
、innerJoin()
の場合はjoin("INNER",...)
です。where()
呼び出しを使用したくないのは、生のクエリ構成からの逸脱が多すぎるためです。ご覧のとおり、新しいinnerJoin()
は新しいINNER JOIN
行を書き込みますが、繰り返しwhere()
を呼び出すと、単一の句が拡張されます。 andWhere() を使用しているのは、 "inner glue"パラメータ(OR
)だけでなく、式をかっこで囲み、最初のwhere()
式を括弧で囲み、論理グループを分離します。 where()
(またはselect()
)の呼び出しに複数の式を記述したい場合は、array()
の条件を指定することをお勧めします。LIKE
の2つの使用方法がありますが、それらを実行するために使用されていません部分一致。これが偶然であったのか、列と文字列を比較する方法についての誤解であったのかはわかりませんが、これはベストプラクティスではなく、将来の研究者を混乱させる可能性があります。ロジックが文字列全体を一致させることである場合は、=
比較演算子を使用します。ロジックが部分一致を行う場合は、LIKE
を使用して、_
または%
を含む文字列を指定します。 LIKE
式で変数を引用する場合は、Joomlaドキュメンテーション 推奨構文 のこのガイドを参照してください。AS
の「構文糖」を好む場合は、必ずそれを使用してください。