web-dev-qa-db-ja.com

1つのクエリで2つのselect()メソッド呼び出しを使用することの混乱

JoomlaのJDatabaseQueryメソッドを使用して、2つの結合されたテーブルからいくつかの列を選択していますが、次のスニペットについて何か理解できません。

_//Initialize variables.
$db = JFactory::getDbo();
$query = $db->getQuery(true);

//Create the base select statement.
$query->select('a.id as id, a.greeting as greeting, a.published as published')
      ->from($db->quoteName('#__diolegend','a'));

//Join over the categories.
$query->select($db->quoteName('c.title' ,'category_title'))
      ->join('LEFT',$db->quoteName('#__categories','c') . ' ON c.id =a.catid');
_

2番目のselect()を参照してください。_a.catid_についての言及はありませんか?

_a.catid_を取得するにはどうすればよいですか?どこからでも選択していません。

2
William Zhao

Joomlaのクエリメソッドselect()はあなたを混乱させたと思います。これが、複数のselect()呼び出しを実行したくない理由です-[〜#〜] one [〜#〜]SELECTのみであるため節が実際に生成されます。

クエリを作成した直後にecho $query->dump();を呼び出すと、次のクエリ文字列が表示されます(_#__の代わりにdbプレフィックスを使用)。

SELECT a.id as id、a.greeting asgreeting、a.published as published、 `c`.`title` AS` category_title`

FROM `lmnop_diolegend` AS` a`

LEFT JOIN `lmnop_categories` AS` c` ON c.id = a.catid

つまり、各列名でselect()を呼び出すことで、同じ生成されたクエリを実現できます。

_->select('a.id AS id')
->select('a.greeting AS greeting')
->select('a.published AS published')
->select('c.title AS category_title')
_

もちろん、結果セットで返すつもりのない列を使用して2つのデータベーステーブルを結合することは完全に有効です。

2つのテーブルを結合することにより、クエリに関係する両方のテーブルから1つまたはすべての列を指定することができます。実際、スクリプトで列を使用するのでない限り、列を含めないことをお勧めします。 _*_の使用は、クエリされたテーブルのすべての列を選択する簡単な方法ですが、不要なデータを返すようにデータベースに要求しても意味がありません。

_GROUP BY_を使用すると、列がSELECT句に含まれていないというエラーメッセージが表示されることがありますが、JOINsではこのエラーは発生しません。


クエリ作成コードに関する注意:

  • メソッドを最初の_$query_宣言に「チェーン」することにより、新しいメソッド呼び出しごとに_$query_を何度も入力する手間を省くことができます。
  • SELECT句で列にエイリアスを使用する場合、列名と同じであればエイリアスを宣言しても意味がありません。 *テーブルエイリアス(_a._および_c._)は、結果セットの要素にアクセスする場合は使用されません。)
  • クエリ作成コードと生成されたクエリの混乱を避けるため、select()を1回だけ使用し、単一の列の文字列を入力して、すべての列が1つの場所に配置されるようにしますコード
  • SQLで問題/エラーを引き起こす文字が列またはテーブル名に含まれていないため、quoteName()呼び出しを省略できます。それらを保持することに害を及ぼすのではなく、単に不要です。
  • 以下のスニペットではASキーワードは必要ありませんが、読みやすさが向上すると思います。
  • 私の答えにシンプルで役立つデバッグ機能を提供することの問題として、_try{}catch{}_ブロック、レンダリングされたクエリのダンプ、および返された行がないかどうかのチェックを含めます。

これが私のローカルホストで成功するためにテストしたスニペットです:

_$db = JFactory::getDbo();
try {
    $query = $db->getQuery(true)
                ->select('a.id, a.greeting, a.published, c.title AS category_title')
                ->from("#__diolegend AS a")
                ->leftJoin("#__categories AS c ON c.id = a.catid");
    echo $query->dump();
    $db->setQuery($query);
    $resultset = $db->loadAssocList();
    if (!$resultset) {
        echo "No Rows In Resultset";
    } else {
        foreach ($resultset as $row) {
            echo "<div>";
                echo "<div>ID: {$row['id']}</div>";
                echo "<div>Greeting: {$row['greeting']}</div>";
                echo "<div>Published: {$row['published']}</div>";
                echo "<div>Category Title: {$row['category_title']}</div>";
            echo "</div>";
        }
    }
} catch (Exception $e) {
    echo "Syntax Error " , $e->getMessage();  // never show `$e->getMessage()` on a public site (only use privately / before your site is live)
}
_

これは出力します:

SELECT a.id、a.greeting、a.published、c.title AS category_title

FROM lmnop_diolegend AS a

LEFT JOIN lmnop_categories AS c ON c.id = a.catid

その後、次のような結果セット:

_ID: 1
Greeting: Hello
Published: 1
Category Title: English

ID: 2
Greeting: Bonjour
Published: 1
Category Title: French
_
1
mickmackusa

テーブル#__deolegendからデータを選択するために使用される$ queryオブジェクトは単純で、同じ$ queryオブジェクトで再びselect()が呼び出され、選択する必要があるフィールドにこれらが追加され、#に結合が追加されます。 c.idおよびa.catidの__categoriesテーブル。つまり、#__ deolegendには列catidが含まれている必要があります。結合を適用するために列を選択する必要はありません。また、以下を使用して$ queryオブジェクトを印刷することをお勧めします:

echo $query;

したがって、最終的なクエリをよりよく理解できます。また、最初にテーブルの構造を確認します。これらについての発見をここで共有できれば、私たちはあなたをより良く支援できるかもしれません。お役に立てれば

1
Pratyush