7

書店のようなものを表すデータベースがあります。書籍が含まれる可能性のあるカテゴリを含むテーブルがあります。一部のカテゴリは、カテゴリとアイテムの関係を含む別のテーブルを使用して定義されます。ただし、プログラムで定義できるカテゴリもいくつかあります。特定の作成者のカテゴリは、クエリ(SELECT item_id FROM items WHERE author = "John Smith")を使用して定義できます。したがって、私のカテゴリテーブルには「クエリ」列があります。nullでない場合は、これを使用してカテゴリ内のアイテムを取得します。それ以外の場合は、category_itemsテーブルを使用します。

現在、アプリケーション(PHPコード)にこの決定を行わせていますが、これは、すべてのカテゴリを反復処理するときに、多くの個別のクエリを意味します。この動的SQLを結合に組み込む方法はありますか?何かのようなもの:

SELECT c.category, IF(c.query IS NULL, count(i.items), count(EXECUTE c.query)
FROM categories c
LEFT OUTER JOIN category_items i
ON c.category = i.category

EXECUTEにはプリペアドステートメントが必要ですが、行ごとに異なるステートメントを準備する必要があります。また、EXECUTEは式では使用できません。これは、単なるトップレベルのステートメントです。提案?

4

2 に答える 2

2

出版社別に本をリストしたい場合はどうなりますか?国?言語?それらすべてを単一の「category_items」テーブルにスローする必要があります。実行する動的クエリをどのように選択しますか?query-within-a-queryメソッドは機能しません。

「カテゴリ」の概念が広すぎるため、SQLが非常に複雑になっていると思います。「カテゴリ」を「ジャンル」(本の場合)のみを表すように置き換えます。ジャンルは独自のテーブルで定義され、item_genresはそれらをitemsテーブルに接続します。著者別の本とジャンル別の本は、データベース/ SQLレベルで同じ(一種の)クエリを使用して両方を実行しようとするのではなく、アプリケーションレベルで別々のクエリにする必要があります。(音楽と本がある場合、それらは異なる概念であるため、おそらくすべてを単一の「アイテム」テーブルに格納するべきではありません...異なるジャンル、著者とアーティストなどがあります。)

私はこれがあなたが望む方法であなたの問題を本当に解決しないことを知っています、しかし私はあなたがそのようにそれをしようとしないことは幸せになると思います。

于 2012-07-12T00:27:36.910 に答える
1

これが私が最終的にPHPクライアントでこれを解決することになった方法です。

category_itemsテーブルのメンバーシップを保持し、送信中に動的クエリを使用してこのテーブルを更新することにしました。

これは、送信中または更新中にアイテムのカテゴリを更新するために呼び出されるスクリプト内の関数です。ユーザーが選択したカテゴリ(動的クエリがないカテゴリからのみ選択可能)のリストを取得し、これと動的クエリを使用して、アイテムが現在含まれているカテゴリとカテゴリの違いを把握します。同期している必要があり、同期させるために必要に応じて挿入/削除します。(私のDBの実際のテーブル名は私の質問と同じではないことに注意してください。私はやや一般的な用語を使用していました。)

function update_item_categories($dbh, $id, $requested_cats) {
    $data = mysql_check($dbh, mysqli_query($dbh, "select id, query from t_ld_categories where query is not null"), 'getting dynamic categories');
    $clauses = array();
    while ($row = mysqli_fetch_object($data))
        $clauses[] = sprintf('select %d cat_id, (%d in (%s)) should_be_in',
            $row->id, $id, $row->query);
    if (!$requested_cats) $requested_cats[] = -1; // Dummy entry that never matches cat_id
    $requested_cat_string = implode(', ', $requested_cats);
    $clauses[] = "select c.id cat_id, (c.id in ($requested_cat_string)) should_be_in
                  from t_ld_categories c
                  where member_type = 'lessons' and query is null";
    $subquery = implode("\nunion all\n", $clauses);
    $query = "select c.cat_id cat_id, should_be_in, (member_id is not null) is_in
              from ($subquery) c
              left outer join t_ld_cat_members m
              on c.cat_id = m.cat_id
              and m.member_id = $id";
    // printf("<pre>$query</pre>");
    $data = mysql_check($dbh, mysqli_query($dbh, $query), 'getting current category membership');
    $adds = array();
    $deletes = array();
    while ($row = mysqli_fetch_object($data)) {
        if ($row->should_be_in && !$row->is_in) $adds[] = "({$row->cat_id}, $id)";
        elseif (!$row->should_be_in && $row->is_in) $deletes[] = "(cat_id = {$row->cat_id} and member_id = $id)";
    }
    if ($deletes) {
        $delete_string = implode(' or ', $deletes);
        mysql_check($dbh, mysqli_query($dbh, "delete from t_ld_cat_members where $delete_string"), 'deleting old categories');
    }
    if ($adds) {
        $add_string = implode(', ', $adds);
        mysql_check($dbh, mysqli_query($dbh, "insert into t_ld_cat_members (cat_id, member_id) values $add_string"),
            "adding new categories");
    }
}
于 2012-08-14T21:27:06.983 に答える