it-swarm.com.de

Joomla 3.3.6 Union SQL-Problem

Ich habe Probleme mit der Verwendung der Gewerkschaftsfunktionen in Joomla. Dies ist die SQL, die ich brauche:

SELECT 
 * 
    FROM
  (SELECT 
    o.title AS org_name,
    u1.name AS username,
    'president' AS `type`
  FROM
    org o 
    LEFT JOIN users u1 
      ON u1.`id` = o.`president` 
  UNION
  ALL 
  SELECT 
    o.title AS org_name,
    u1.name AS username,
    'secretary' AS `type`
  FROM
    org o 
    LEFT JOIN users u1 
      ON u1.`id` = o.`secretary` 
  UNION
  ALL 
  SELECT 
    o.title AS org_name,
    u1.name AS username,
    'treasurer' AS `type`
  FROM
    org o 
    LEFT JOIN users u1 
      ON u1.`id` = o.`treasurer`) AS a 
ORDER BY a.org_name ;

Dies ist mein Joomla-Code:

    $q2 = $db->getQuery(true);
    $q1 = $db->getQuery(true);
    $query  = $db->getQuery(true);

    $q2
    ->select('o.title AS show_name, u1.name AS name,' . $db->quoteName('president') . 'as' . $db->quoteName('type'))
    ->from($db->quoteName('#__agshows_shows', 'o'))
    ->join('LEFT', $db->quoteName('#__users', 'u1') . ' ON (' . $db->quoteName('u1.id') . ' = ' . $db->quoteName('o.president') . ')')      
    ;
    $q1
    ->select('o.title AS show_name, u1.name AS name')
    ->from($db->quoteName('#__agshows_shows', 'o'))
    ->join('LEFT', $db->quoteName('#__users', 'u1') . ' ON (' . $db->quoteName('u1.id') . ' = ' . $db->quoteName('o.secretary') . ')')      
    ;
    $query
    ->select('*')
    ->from($db->quoteName('#__agshows_shows', 'a'))     
    ->union($q1)
    ->union($q2)
    ->order($db->quoteName('a.title') . ' ASC')
    ;
$mailshot = $db->setQuery($query)->loadObjectList();

Ich erhalte immer wieder den folgenden SQL-Fehler:

1221 Falsche Verwendung von UNION und ORDER BY SQL = SELECT * FROM ruq1h_agshows_shows AS a ORDER BY a.title ASC UNION (SELECT o.title AS show_name, u1.name AS name FROM ruq1h_agshows_shows AS o LEFT JOIN ruq1h_users WIE u1 AUF (u1.id = o.secretary)) UNION (SELECT o.title AS show_name, u1.name AS name, presidentas type VON ruq1h_agshows_shows AS o LEFT JOIN ruq1h_users WIE u1 AUF (u1.id = o.president))

Was mache ich falsch?

2
Lee Wiggins

So debuggen Sie das Problem: $ query ist ein Objekt, das die auszuführende SQL-Anweisung generiert. Dann können Sie $ query -> __ toString () wiederholen und die Ausgaben vergleichen.

In einem komplexen Fall kann es erforderlich sein, Unterabfragen zu generieren, um eine endgültige große Abfrage zu erstellen.

2
Anibal

Ein paar Punkte:

  1. Sie haben wirklich eine Rute für Ihren Rücken gemacht, indem Sie Ihre org Tabelle nicht "normalisiert" haben. Ich empfehle dringend, die Tabelle org so umzustrukturieren, dass sie eine type -Spalte gegenüber drei statischen Spalten enthält. Dies bedeutet, dass Sie die Anzahl der Zeilen in Ihrer Tabelle verdreifachen müssen. Während diese neue Struktur weniger komprimiert aussieht, können Sie mit ihr wesentlich mehr saubere/direkte Abfragen Ihrer Daten durchführen.

  2. Wenn Sie WISSEN, dass kein Benutzer jemals mehr als eine Position innehat (in einer Organisation) UND Sie keine offenen Positionen oder nicht besetzten Benutzer sehen möchten, können Sie Folgendes verwenden:

    SELECT
    b.title AS org_name,
    a.name AS username,
    MAX(CASE a.id
        WHEN president THEN 'president'
        WHEN secretary THEN 'secretary'
        WHEN treasurer THEN 'treasurer'
        ELSE NULL END) AS type
    FROM `users` a
    INNER JOIN `org` b ON a.id IN (b.president, b.secretary, b.treasurer)
    GROUP BY a.id
    
  3. Andernfalls ist die folgende Abfrage, um eine MySQL-Abfrage zu erstellen, die Benutzer mit mehreren Sitzen aufnehmen kann, mit den UNION ALL-Klauseln etwas komplizierter, jedoch etwas sauberer als der von Ihnen veröffentlichte Versuch.

    SELECT o.title AS org_name, u.name AS username, 'president' AS `type`
    FROM org o
    LEFT JOIN users u ON u.id = o.president
    UNION (
        SELECT o.title, u.name, 'secretary'
        FROM org o 
        LEFT JOIN users u ON u.id = o.secretary
    )
    UNION (
        SELECT o.title, u.name, 'treasurer'
        FROM org o 
        LEFT JOIN users u ON u.id = o.treasurer
    )
    ORDER BY org_name, type
    

    Anmerkungen:

    • Die SELECT-Spalten müssen nur in der ersten SELECT-Anweisung angegeben werden (die Spalten sind bei nachfolgenden Vereinigungen impliziert).
    • Wenn Sie keine leeren Plätze in Ihre Ergebnismenge aufnehmen möchten (wobei der Benutzername NULL für einen bestimmten Platz ist), ersetzen Sie alle LEFT JOINs durch INNER JOINs.

PHP/Joomla-Syntax für die Abfrage mit UNION ALLs:

$db = JFactory::getDBO();
$query = $db->getQuery(true)
    ->select([
        "o.title AS org_name",
        "u.name AS username",
        $db->q("president") . " AS `type`"
    ])
    ->from('org o')
    ->innerJoin("users u on u.id = o.president")
    ->order("org_name, type");

$types = ['secretary', 'treasurer'];
foreach ($types as $type) {
    $query->union($db->getQuery(true)
                     ->select("o.title, u.name, " . $db->q($type))
                     ->from("org o")
                     ->innerJoin("users u ON u.id = " . $db->qn("o.{$type}"))
    );
}

$db->setQuery($query);
echo $query->dump();  // see the generated query
try {
    if (!$result = $db->loadAssocList()) {
        echo "No Qualifying Rows";
    } else {
        echo "<table>";
            echo "<tr><th>", implode("</th><th>", array_keys($result[0])), "</th></tr>";
            foreach ($result as $row) {
                echo "<tr><td>", implode("</td><td>", $row), "</td></tr>";
            }
        echo "</table>";
    }
} catch (Exception $e) {
    JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error');  // never show getMessage() to public
}

Testschemata mit SQL Demo

Ausgabe von Beispieldaten:

SELECT o.title AS org_name,u.name AS username,'president' AS `type`
FROM org o
INNER JOIN users u on u.id = o.president
UNION (
SELECT o.title, u.name, 'secretary'
FROM org o
INNER JOIN users u ON u.id = `o`.`secretary`)
UNION (
SELECT o.title, u.name, 'treasurer'
FROM org o
INNER JOIN users u ON u.id = `o`.`treasurer`)
ORDER BY org_name, type
| org_name | username               | type      |
| -------- | ---------------------- | --------- |
| ACA Qld  | Majella Fitzsimmons    | president |
| ACA Qld  | Debra North            | secretary |
| ACA Qld  | Doug Burns             | treasurer |
| BMWMCQ   | Paul Hughes            | president |
| BMWMCQ   | Duncan Bennett         | secretary |
| BMWMCQ   | John Eacott            | treasurer |
| Joomla   | Rowan Hoskyns Abrahall | president |
| Joomla   | Luca Marzo             | secretary |
| Joomla   | Jason Rosenbaum        | treasurer |
1
mickmackusa

Sie müssen jede Abfrage wie zuvor erstellen ($ q1, $ q2, $ q3 usw.) und eine abschließende Abfrage wie folgt erstellen:

$query->select("tab.*")
      ->from("(".$q1->union($q2)->union($q3).") as tab")
      ->order("tab.orderingField");

In diesem Artikel wird dies gut erklärt: https://docs.joomla.org/Using_the_union_methods_in_database_queries#Ordering_results

1
Kitase88