Views3 und Unterabfragen?

12

Ich habe eine Ansicht, die eine Abfrage generiert, die mehrere Verknüpfungen ausführt. Dies erzeugt eine kartesische Verknüpfung, und ich muss die Verknüpfungen in Unterabfragen "konvertieren".

Ich habe in der Dokumentation, in den Google-Suchergebnissen und in anderen Quellen nachgeschlagen, finde jedoch keine anständige Beschreibung, wie ich Views für Unterabfragen konfigurieren kann. Ich habe hook_views_data () verwendet, um die Beziehungen zu konfigurieren (die jetzt als Joins ausgeführt werden). Ist es irgendwie möglich, Unterabfragen über hook_views_data () zu definieren, oder muss ich einen anderen Ansatz wählen?

Jeder Rat geschätzt!

sbrattla
quelle

Antworten:

5

Ich schaute weiter, konnte aber keine Dokumentation finden, die dies beschreibt.

Was ich brauchte, war eine Möglichkeit, die Benutzertabelle mit zwei anderen Tabellen zu verbinden, die Daten für die Benutzer enthalten. Die beiden anderen Tabellen stehen jedoch in einer Eins-zu-Viele-Beziehung zur Benutzertabelle, was bedeutet, dass ich einen kartesischen Join erhalte, wenn ich versuche, die Benutzertabelle gleichzeitig mit diesen beiden Tabellen zu verknüpfen . Da ich jedoch nur die Anzahl der Datensätze in den beiden anderen Tabellen zählen muss, die einem bestimmten Benutzer zugeordnet sind, sollte eine Unterabfrage in der Lage sein, diesen Trick auszuführen. Ich konnte jedoch keine Dokumentation zu Ansichten und Unterabfragen finden. Deshalb habe ich Folgendes getan.

  1. Erstellt zwei Dummy-Felder

Ich habe über hook_views_data () zwei Dummy-Felder erstellt (die ich "Downloads" und "Listenens" nennen werde). Die Definition des Feldes ist unten aufgeführt.

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',
      ),
    )
  ),
);

Wenn Sie nun eine Ansicht für Benutzer konfigurieren, werden die Felder "Downloads" und "Listenens" angezeigt. Der Versuch, jetzt eine Abfrage auszuführen, führt jedoch zu einem Fehler, da es sich bei den Dummy-Feldern immerhin um Dummy-Felder handelt. Sie existieren nicht. Der einzige Zweck dieser Felder besteht darin, unserer Implementierung von hook_views_query_alter () zu signalisieren, dass einige Ersetzungssätze erforderlich sind.

  1. Implementiere hook_views_query_alter ()

Der Trick dabei ist zu prüfen, ob die angegebene Abfrage die Felder "Downloads" oder "Listenens" enthält. In diesem Fall werden die Felder aus der Abfrage entfernt und durch Unterabfragen ersetzt. Die Implementierung dieser Funktion erfolgt wie folgt.

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;
      }
    }
  }
}

Beachten Sie, dass wir den Alias ​​des entfernten Felds für die Unterabfrage wiederverwenden. Auf diese Weise wird Views annehmen, dass der von der Unterabfrage zurückgegebene Wert tatsächlich aus dem Dummy-Feld stammt (das schließlich nicht existiert).

Das ist es. Wir bekommen keinen Cartesian Join und sowohl "Downloads" als auch "Listenens" werden korrekt gezählt.

sbrattla
quelle
4

Ich habe die Lösung von sbrattla verwendet, bis die Unterabfrage die Filterwerte übernehmen musste. Ich verwende jetzt das Modul views_field_view , um eine separate Ansicht einzubetten, die die Zählabfrage ausführt. Ich kann der eingebetteten Ansicht Kontextfilterwerte über das Modul views_filterfield (das ich geschrieben habe) übergeben, das Filterwerte als Ansichtsfelder (und damit als Token) zur Verfügung stellt.

Die Zählabfrage funktioniert jetzt und erbt die angezeigten Filter in der Hauptabfrage.

Cafuego
quelle