varchar(255)
フィールドがJdatabase
commasで区切られた値を含むテーブル。正確には、カンマで区切られた数値が含まれています。
カスタム[〜#〜] php [〜#〜]モジュールを使用して個々の値を取得したい。実際には、IDのコンマ区切りリストに存在するIDを持つ別のテーブルからレコード(データを取得)を選択する必要があります。
これを達成するための最良の方法は何でしょうか?
最初にカンマを選択し、次にIDがその文字列内にあるかどうかを確認するだけの2つの単純なクエリ。ちょうどテストされ、$db->loadResult()
からフェッチされた$commas
文字列値を持つMySql IN()関数を使用して機能します。
もっと簡単なことはできません。
// First get all commas
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->qn('Commas'))
->from($db->qn('#__classes_attended'))
->where($db->qn('Id') . ' = 1');
$db->setQuery($query);
$commas = $db->loadResult();
// Select them from second table
$query = $db->getQuery(true);
$query->clear();
$query->select($db->qn('Data_needed'))
->from($db->qn('#__jdatabse_table_2'))
->where($db->qn('Id') . ' IN (' . $commas . ')');
$db->setQuery($query);
$results = $db->loadObjectList();
これを達成するための最良の方法は何でしょうか?
この質問について、私が共有しなければならない「ベストプラクティス」は2つあります。
必要以上にデータベースにアクセスしないでください。
クエリロジックは単一のクエリにベイクできるため、そうする必要があります。このインスタンスで呼び出すヒーローは FIND_IN_SET() です。 IN
と同じように機能しますが、 IN
は、カンマ区切りの列値では機能しません です。
生のクエリ:( db-fiddle.com demo )
_SELECT name
FROM `#__table2`
WHERE FIND_IN_SET(id, (SELECT classes_attended FROM `#__table1` WHERE id = 1))
_
*これはサブクエリの代わりにJOINとして実行することもできます(スニペットの上のstackoverflowリンクに示されているように)が、1つの行に一度だけ関連付ける必要があるため、この方法をお勧めします。
Joomla/PHP構文:(ローカルでテスト済み。クエリダンプとエラーチェックが含まれます)
_$id = 1;
try {
$db = JFactory::getDbo();
$subquery = $db->getQuery(true)
->select($db->qn("classes_attended"))
->from($db->qn("#__table1"))
->where($db->qn("id") . " = " . (int)$id);
$query = $db->getQuery(true)
->select($db->qn("name"))
->from($db->qn("#__table2"))
->where("FIND_IN_SET(" . $db->qn("id") . ", (" . $subquery . "))");
$db->setQuery($query);
JFactory::getApplication()->enqueueMessage($query->dump(), 'info'); // don't show your rendered query to the public
if (!$result = $db->loadColumn()) {
echo "<p>No Rows Found</p>";
} else {
echo "<pre>";
var_export($result); // prints indexed single-dimensional array of values
echo "</pre>";
}
} catch (Exception $e) {
JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error'); // don't show $e->getMessage() to public
}
_
データ構造を正規化します。FIND_IN_SET()
の使用は、データベース設計が最適化されていないことを示しています。
私の言葉を理解しないでください Bill Karwin -文字通り書いた人 悪いSQLコーディング慣行に関する本 を聞いてください。
このクエリをインデックスで最適化することはできません。これは、値のコンマ区切りのリストを格納することがリレーショナルデータベースで悪い考えである理由の1つです。
ソース: https://stackoverflow.com/a/44183060/29434
この場合のデータの正規化とは、新しいテーブルを作成し、_classes_attended
_データをid
および_class_attended
_を含む行に抽象化することを意味します。そうすることで、データのクエリが容易になり、より複雑なクエリを効率よく作成できるようになります。
_ id | classes_attended
-----------------------------------
1 | 1,3,6,7
_
なる
_ id | class_attended
---------------------------------
1 | 1
1 | 3
1 | 6
1 | 7
_
正規化 に関する初心者向けのリンクを以下に示します。