新しいテーブル_clients
を作成しようとしています。これには、現在のところ、user_id
の#__user_usergroup_map
列が単純に入力されています。
理想的には、以下のコードは、#__user_usergroup_map
に一致し、group_id = 10
テーブル内にまだ存在しないIDのみがある場合、_clients
テーブルからすべてのid
をプルする必要があります。
これは、phpmyadminのgroup_id = 10
でユーザーを追加/削除したときに機能するようです。 $ncl
は正しいリストを示しています。
#__clients
はページの更新時に正常に更新されますが、#__clients
に主キーが重複して挿入されるとSQLエラーが発生します。同じユーザーを#__clients
に再度追加しようとしているようです(最初の更新時にユーザーがテーブルに追加されました)。
これらのクライアントIDは$ncl
テーブルにまだないため、このコードは#__clients
のみを選択する必要があると思いました。誰かが何か考えがありますか?
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$query->select('a.user_id', 'a.group_id', 'b.id')
->from('#__user_usergroup_map as a', '#__clients as b');
$query->join('RIGHT', '#__clients AS b ON a.user_id != b.id')
->where('a.group_id = ' . $db->quote("10"));
$db->setQuery($query);
$ncl = $db->loadColumn();
print_r($ncl);
foreach($ncl as $encl) {
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->insert('#__clients')
->set('id = ' . (int) $encl);
$db->setQuery($query);
$db->execute();
}
コードを次のように調整できます。
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$query->select('a.user_id as id') /* changed to load object and insert it */
->from('#__user_usergroup_map as a')
->leftJoin('#__clients AS b ON a.user_id = b.id') /* you should join with "=" not with "!=" */
->where('a.group_id = ' . $db->quote("10"))
->where('b.id IS NULL'); /* and filter to "new only" like this */
$ncl = $db->setQuery($query)->loadColumn();
print_r($ncl);
foreach($ncl as $encl) {
$db->insertObject('#__clients',$encl); /* less code this way */
}
このコードでうまくいきますが、さらに進んでそれを作ることができます
$db = JFactory::getDBO();
$sel_query = $db->getQuery(true);
$ins_query = $db->getQuery(true);
$sel_query->select('a.user_id as id')
->from('#__user_usergroup_map as a')
->leftJoin('#__clients AS b ON a.user_id = b.id')
->where('a.group_id = ' . $db->quote("10"))
->where('b.id IS NULL');
$ins_query->insert('#__clients')
->columns('id')
->values($sel_query);
$db->setQuery(str_replace('VALUES','',$ins_query))->execute();
このようにして、単一のリクエストでジョブを実行します。
私は今、より単純な方法を実現しました...すでに既存の配列を作成していたので、次のようなものを単に使用できます:
$filteredFoo = array_diff($foo, $bar);
これにより、各テーブルを表す2つの配列から重複が除外され、重複のリスクなしに$ filteredFooでSQL挿入が実行されます。
_#__user_usergroup_map
_から_#__clients
_へのINSERTデータのみが必要なので、id
はnullであり、_group_id
_は_10
_であるので、_LEFT JOIN
_を使用する必要がありますテーブルを結合します。他の結合は、NULL
列を生成する行を排除し、それは望ましくありません。
_| #__user_usergroup_map | LEFT JOIN ON user_id=id | #__clients |
|------------------------| < |--------------|
| user_id | group_id | < | id |
|-----------|------------| < |--------------|
| 1 | 10 | < | NULL |
| 2 | 9 | < | NULL |
| 3 | 10 | < | NULL |
| 4 | 6 | < | NULL |
| 5 | 10 | < | 5 | //previously INSERTED for demonstration's sake
| 6 | 10 | < | NULL |
| 7 | 10 | < | NULL |
| 8 | 10 | < | NULL |
| 9 | 4 | < | NULL |
| 10 | 10 | < | NULL |
-------------------------- ----------------
_
解決策に入る前に、php/Joomla構文が意図したクエリを生成していないという事実に注目したいと思います。
_$query = $db->getQuery(true) ->select('a.user_id', 'a.group_id', 'b.id') ->from('#__user_usergroup_map as a', '#__clients as b') ->join('RIGHT', '#__clients AS b ON a.user_id != b.id') ->where('a.group_id = ' . $db->quote("10")); echo $query->dump();
_
生成:
_SELECT a.user_id // 2nd & 3rd columns are lost (should have been written as an array, but they were unimportant anyhow)
FROM prefx_user_usergroup_map as a // comma joined table is lost (not that it was good for anything)
RIGHT JOIN prefx_clients AS b ON a.user_id != b.id // this is not the correct join, nor ON logic
WHERE a.group_id = '10' // this is half of what is required
_
これはゼロ行を返します。
ロジック/構文がしっかりしているため、Alexandrのスニペットが期待どおりの結果を提供すると確信していますが、いくつかの違いがあるバージョンを提供します。
_$db = JFactory::getDBO();
try {
$select_query = $db->getQuery(true)
->select("A.user_id")
->from("#__user_usergroup_map A")
->leftJoin("#__clients B ON A.user_id = B.id")
->where("A.group_id = 10 AND B.id IS NULL");
//echo $select_query->dump();
$insert_query = $db->getQuery(true)
->insert('#__clients')
->columns('id')
->values($select_query);
// echo $insert_query->dump();
$db->setQuery($insert_query);
$db->execute();
// echo $db->getAffectedRows() , " row(s) inserted into clients table";
} catch (Exception $e) {
echo "Syntax Error"; // . " & Error: " . $e->getMessage();
}
_
私は自分のスニペットをローカルホストで成功するようにテストしました。私は SQLFiddle Demo も作成しました。
${Word}_query
_の重複した記述を排除するために、getQuery()
メソッドからの各クエリをチェーンしています。qn()
またはq()
呼び出しは、解析/セキュリティ上の理由で必要ないため、使用していません。SELECT
の列は必要ないため、エイリアスを設定していません。setQuery(str_replace('VALUES','',$ins_query))
は必要ありません。Alexandrのソリューションを恥知らずに盗んでいると誰かが心配している場合は、_#__clients.id
_列が_PRIMARY/UNIQUE KEY
_であると仮定して同じ効果を持つ別のブルートフォースクエリビルドを投稿します。私はこのエレガントでないソリューションを使用するとは思いません(何らかの理由で、パフォーマンスが少し向上したとしても)。
_$select_query = $db->getQuery(true)
->select("A.user_id")
->from("#__user_usergroup_map A")
->where("A.group_id = 10");
// echo $select_query->dump();
$insert_query = $db->getQuery(true)
->insert('#__clients')
->columns('id')
->values($select_query);
$db->setQuery(str_replace("INSERT", "INSERT IGNORE", $insert_query));
_