web-dev-qa-db-ja.com

2つのビューの和集合を作成する方法は?

「投稿日」でソートされたユーザーのノードとコメントの結合を取得しようとしています。この post はD6のサンドボックスプロジェクトにリンクしていますが、7には何もありません。

この post には、D6でhook_views_pre_execute()およびSQL UNIONを使用する例があります。これは、ビュー3のD7では機能しません。

Merlinofchaosに出くわした コメント

現在Drupalの新しいクエリジェネレータを使用しているため、クエリはSelectQueryオブジェクトであり、変更または置換する必要があります。詳細については、Drupal 7の新しいデータベースレイヤーを参照してください。

これを行う方法の例、または2つのビューを組み合わせる他のソリューションの例はありますか?

36
uwe

これが実際にテストされた例です:

/**
 * Implements hook_views_pre_execute().
 */
function mymodule_views_pre_execute(view &$view) {
  if ($view->name == 'my_view') {
    $query1 = &$view->build_info['query'];

    // Basic setup of the second query.
    $query2 = db_select('another_table', 'at')
      ->condition('some_field', 0, '>')
      ->condition('some_other_field', 12345);

    // The number of fields (and their aliases) must match query1.
    // Get the details with:
    // dpm($query1->getFields());
    $query2->addField('at', 'some_field', 'alias1');
    $query2->addField('at', 'some_other_field', 'alias2');
    $query2->addField('at', 'some_other_field2', 'alias3');
    $query2->addField('at', 'some_other_field3', 'alias4');

    // Verify that queries are very similar.
    // dpq($query1);
    // dpq($query2);

    // Matrimony.
    $query1 = $query2->union($query1, 'UNION ALL');

    // Manual test.
    // dpm($query1->execute()->fetchAll());

  }
}

これはほとんどのビューで機能します。ただし、一部のスタイルプラグインは、この手法(私が見ているカレンダーモジュール)で機能しない空想的なことを行う場合があります。

15
Dalin

ビュー追加ハンドラーモジュールを使用して、2つの異なるビュー/ディスプレイからSQL UNIONクエリを生成できます。

Drupal.orgの詳細なチュートリアル here

https://www.drupal.org/project/views_extra_handlers screenshot of views alter settings

3
TechNikh

最終的に、db_query()を使用してSQL UNIONを作成し、theme()関数を使用してページャーを含むテーブルレイアウトにレンダリングしました。

ユーザーにとっては、デフォルトのビューのように見えます。もう1つの利点は、クエリを大幅に最適化できることです。私は「私の友人の活動」を表示しています。そのためにビューを使用すると、友人のリストが作成され、SQLの "IN"句で使用されるため、レコード数が50または100を超えると非常に遅くなります。

友達のリストを、過去x日間にサイトにログインした友達だけに絞り込むことができます。

これはコードサンプルです:

  // Two queries are required (friendships can be represented in 2 ways in the
  // same table). No point making two db calls though so a UNION it is.

  // Build up the first query.
  $query = db_select('flag_friend', 'f')
    ->condition('f.uid', $account->uid)
    ->condition('u.login', $timestamp, '>');
  $query->addExpression('f.friend_uid', 'uid');
  $query->innerJoin('users', 'u', 'u.uid = f.friend_uid');

  // Build up the second query.
  $query2 = db_select('flag_friend', 'f')
    ->condition('f.friend_uid', $account->uid)
    ->condition('u.login', $timestamp, '>');
  $query2->addExpression('f.uid', 'uid');
  $query2->innerJoin('users', 'u', 'u.uid = f.uid');

  // Return the results of the UNIONed queries.
  return $query->union($query2)->execute()->fetchCol();
2
uwe

将来の参考のために、これは同じテーブルに基づいて2つのビューを組み合わせる方法です。同じ量のフィールドを持つ異なるテーブルに基づくビューにも同じ原則を適用する必要があります。

以下の例では、フォーマットがレンダリングされたエンティティに設定されているため、idのみが選択されています。ただし、フィールドを使用する場合は、以下のタイムスタンプを追加したので、フィールドが少ないクエリにダミーフィールドをいつでも追加できます。

/**
 * Implements hook_views_pre_execute().
 */
function MY_MODULE_views_pre_execute(&$view) {
  if ($view->name == 'VIEW_1' && $view->current_display == 'DISPLAY_OF_VIEW_1') {

    $view2 = views_get_view('VIEW_2');
    $view2->build('DISPLAY_OF_VIEW_2');

    $view->build_info['query']
    ->fields('table_alias', array('timestamp'))
    ->union(
        $view2->build_info['query']
        ->range()
        ->fields('table_alias', array('timestamp'))
        ->orderBy('timestamp', 'DESC')
    );

    $view->build_info['count_query']
    ->union(
        $view2->build_info['count_query']
        ->range()
    );
  };
}
1
duru

Views Field View というモジュールに出会いました。これにより、ビューをフィールドとして別のビューに埋め込むことができます。私自身はまだこれを試していませんが、参考になるかもしれません。

0

私はそれらがこれらの線に沿って何かを想像します:

/** 
* Implements hook_views_pre_execute().
*/     
function mymodule_views_pre_execute(&$view) {
  if ($view->name == 'myview') {
    $query = $view->query;
    $other_view = views_get_view('otherview');
    $other_query = $other_view->query;
    $query = $query->union($other_query);
    $view->query = $query;
  }
}

私はそれをテストしていませんが。

役立ついくつかのリンク:

http://api.drupal.org/api/drupal/includes!database!select.inc/function/SelectQueryInterface%3A%3Aunion/7

http://drupal.org/node/557318#comment-199191

0
cam8001

EntityFieldQuery Views Backend は、同時に複数のエンティティタイプのクエリをサポートします。したがって、ノードとコメントの両方のクエリに使用できるはずです。どちらのエンティティタイプもuidプロパティを使用して作成者にリンクしているため、APIレベル EntityFieldQuery :: propertyCondition() を使用して、単一のユーザーからノードとコメントを選択できます。ビューのバックエンドが同じ機能を提供すると思います。

0
Pierre Buyle

別のアプローチとして、ノードとコメントのfeedsを作成し(URL内のユーザーIDのコンテキストフィルターを使用)、2つのフィードを組み合わせて新しいフィードを作成し、これを投稿日ごとに表示することができます。

0
Sam Wilson