Views3とサブクエリ?


12

複数の結合を行うクエリを生成するビューがあります。これによりデカルト結合が生成され、結合をサブクエリに「変換」する必要があります。

ドキュメント、Googleの検索結果、その他のソースを調べましたが、サブクエリを実行するためにビューを構成する方法についての適切な説明を見つけることができません。hook_views_data()を使用して、リレーションシップを構成しました(現在は結合として実行されています)。hook_views_data()を介してサブクエリを定義することは何らかの形で可能ですか、それとも別のアプローチをとる必要がありますか?

アドバイスをいただければ幸いです!

回答:


5

さらに調べましたが、これを説明するドキュメントは実際には見つかりませんでした。

私が必要としたのは、ユーザーのデータを保持する他の2つのテーブルとユーザーテーブルを結合する方法でした。ただし、他の2つのテーブルはユーザーテーブルと「1対多」の関係にあります。つまり、ユーザーテーブルとこれらのテーブルの両方を同時に結合しようとすると、デカルト結合になります。 。ただし、必要なのは、特定のユーザーに関連付けられた他の2つのテーブルのレコード数をカウントすることだけなので、サブクエリでトリックを実行できるはずです。ただし、ビューとサブクエリに関するドキュメントが見つかりませんでした。ここで、私がしたことを説明します。

  1. 2つのダミーフィールドを作成しました

hook_views_data()を介して2つのダミーフィールド(「ダウンロード」および「リッスン」と呼びます)を作成しました。フィールドの定義を以下にリストします。

function hook_views_data() {

  $data['users'] = array(
    'downloads' => array(
      'title' => t('Downloads'),
      'field' => array(
        'handler' => 'views_handler_field_numeric',
        'click sortable' => TRUE,
      ),
      'filter' => array(
        'handler' => 'views_handler_filter_numeric',
      ),
      'sort' => array(
        'handler' => 'views_handler_sort',
      ),
    ),
    'listens' => array(
      'title' => t('Listens'),
      'field' => array(
        'handler' => 'views_handler_field_numeric',
        'click sortable' => TRUE,
      ),
      'filter' => array(
        'handler' => 'views_handler_filter_numeric',
      ),
      'sort' => array(
        'handler' => 'views_handler_sort',
      ),
    )
  ),
);

これで、ユーザーのビューを設定すると、「ダウンロード」フィールドと「リスニング」フィールドが表示されます。ただし、クエリを実行しようとすると、ダミーフィールドがすべてダミーフィールドであるため、エラーが発生します。それらは存在しません。これらのフィールドの唯一の目的は、hook_views_query_alter()の実装に、いくつかの置き換えを行う必要があることを知らせることです。

  1. hook_views_query_alter()を実装する

ここでのコツは、指定されたクエリに「ダウンロード」または「リスニング」フィールドが含まれているかどうかを確認することです。存在する場合、クエリからフィールドを削除し、サブクエリに置き換えます。この関数の実装は以下の通りです。

function mta_views_query_alter(&$view, &$query) {

  foreach ($query->fields as $field_key => &$field_values) {
    if ($field_values['table'] == 'users') {

      switch ($field_values['field']) {
        case 'downloads':
          unset($query->fields[$field_key]);
          $query->add_field(null, "(SELECT COUNT(*) FROM {fileusage} fu WHERE fu.externaluser = {users}.uid AND fu.action = 0)", $field_key);
          break;
        case 'listens':
          unset($query->fields[$field_key]);
          $query->add_field(null, "(SELECT COUNT(*) FROM {fileusage} fu WHERE fu.externaluser = {users}.uid AND fu.action = 1)", $field_key);
          break;
      }
    }
  }
}

サブクエリの削除されたフィールドのエイリアスを再利用していることに注意してください。そうすることで、Viewsは、サブクエリから返された値が実際にはダミーフィールド(結局は存在しません)から返されたものだと考えます。

そうです。デカルト結合を取得していないため、「ダウンロード」と「リッスン」の両方が正しくカウントされます。


4

サブクエリにフィルター値を継承させる必要があるまで、sbrattlaのソリューションを使用しました。私は、views_field_viewモジュールを使用して、カウントクエリを実行する別のビューを埋め込みます。ビューフィールド(およびトークン)としてフィルター値を使用できるようにするviews_filterfieldモジュール(作成した)を介して、その埋め込みビューにコンテキストフィルター値を渡す ことができます。

これで、カウントクエリが機能し、メインクエリで公開されたフィルターを継承します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.