it-swarm.com.de

Wie kann ich bestimmte Zeilen aus einer Tabelle abfragen, die auf anderen zugeordneten Zeilen in derselben Tabelle basieren?

Ich versuche, meine Tabelle jos_rsform_submission_values Nach FieldValue Daten in Zeilen mit einem FieldName von Container# Abzufragen, der ein SubmissionId mit einem anderen teilt Zeile, in der FieldValue "Ausstehend" und FieldName "Status #" und # nach "Status" = # nach "Container" ist .

Hier sind einige Beispieltabellendaten, damit ich besser ausdrücken kann, wonach ich gesucht habe:

CREATE TABLE `jos_rsform_submission_values` (
  `SubmissionValueId` int(11) NOT NULL,
  `FormId` int(11) NOT NULL,
  `SubmissionId` int(11) NOT NULL DEFAULT '0',
  `FieldName` text NOT NULL,
  `FieldValue` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `jos_rsform_submission_values` (`SubmissionValueId`, `FormId`, `SubmissionId`, `FieldName`, `FieldValue`) VALUES
(129862, 28, 548, 'creationdate', '27-08-2018 10:30 AM'),
(129863, 28, 548, 'CustomerAccount', 'TEST'),
(129864, 28, 548, 'otheraccount', ''),
(129865, 28, 548, 'salesorderno', 'SO-00006296'),
(129866, 28, 548, 'DocumentUpload', '-'),
(129867, 28, 548, 'numberofbayan', '1'),
(129868, 28, 548, 'BayanNo', '189426'),
(129869, 28, 548, 'portofloading', 'Seaport'),
(129870, 28, 548, 'containers', '3'),
(129871, 28, 548, 'Container1', 'TTNU8517512'),
(129872, 28, 548, 'CargoDescription1', 'Chocolate'),
(129873, 28, 548, 'containertype1', 'Reefer'),
(129874, 28, 548, 'purchaseorder1', ''),
(129875, 28, 548, 'Location1', 'Jeddah'),
(129876, 28, 548, 'Status1', 'Return Empty'),
(129877, 28, 548, 'requesteddate1', '18-08-2018 07:00 AM'),
(129878, 28, 548, 'Container2', 'TCLU1256192'),
(129879, 28, 548, 'CargoDescription2', 'Chocolate'),
(129880, 28, 548, 'containertype2', 'Reefer'),
(129881, 28, 548, 'purchaseorder2', ''),
(129882, 28, 548, 'Location2', 'Jeddah'),
(129883, 28, 548, 'Status2', 'Return Empty'),
(129884, 28, 548, 'requesteddate2', '18-08-2018 07:00 AM'),
(129885, 28, 548, 'Container3', 'KKFU6780793'),
(129886, 28, 548, 'CargoDescription3', 'Chocolate'),
(129887, 28, 548, 'containertype3', 'Reefer'),
(129888, 28, 548, 'purchaseorder3', ''),
(129889, 28, 548, 'Location3', 'Jeddah'),
(129890, 28, 548, 'Status3', 'Pending'),
(129891, 28, 548, 'requesteddate3', '18-08-2018 07:00 AM'),
(129892, 28, 548, 'Container4', ''),
(129893, 28, 548, 'CargoDescription4', ''),
(129894, 28, 548, 'containertype4', ' '),
(129895, 28, 548, 'purchaseorder4', ''),
(129896, 28, 548, 'Location4', '-'),
(129897, 28, 548, 'Status4', ' '),
(129898, 28, 548, 'requesteddate4', ''),
(129899, 28, 548, 'Container5', ''),
(129900, 28, 548, 'CargoDescription5', ''),
(129901, 28, 548, 'containertype5', ' '),
(129902, 28, 548, 'purchaseorder5', ''),
(129903, 28, 548, 'Location5', '-'),
(129904, 28, 548, 'Status5', ' '),
(129905, 28, 548, 'requesteddate5', '')

ALTER TABLE `jos_rsform_submission_values`
  ADD PRIMARY KEY (`SubmissionValueId`),
  ADD KEY `FormId` (`FormId`),
  ADD KEY `SubmissionId` (`SubmissionId`),
  ADD KEY `SubmissionId_2` (`SubmissionId`),
  ADD KEY `SubmissionId_3` (`SubmissionId`);

ALTER TABLE `jos_rsform_submission_values`
  MODIFY `SubmissionValueId` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=133092;

Von den oben genannten hat nur SubmissionId548 einen Status Wert von Pending.

## SubmissionId    FieldName    FieldValue
## -----------------------------------------
##     548         Status1      Return Empty
##     548         Status2      Return Empty
##     548         Status3      Pending
##     548         Status4      
##     548         Status5

Ich muss den entsprechenden Container # Wert finden:

## SubmissionId    FieldName    FieldValue
## ----------------------------------------
##     548         Container3   KKFU6780793

Zusätzliche Details:

In Bezug auf meine übermittelten Daten beginnen die FieldName -Werte mit einer von fünf Zeichenfolgen: "Status", "Container", "ContainerType", "ExpDate" und "Commodity", gefolgt von einer Zahl ab 1 aber kann so hoch sein wie 10.

Mein Codierungsversuch:

<?php 
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName(array('FieldName')));
$query->from($db->quoteName('#__rsform_submission_values'));
$query->where($db->quoteName('FieldName') . ' IN ("Status1","Status2","Status3","Status4" ,"Status5")');
$query->where($db->quoteName('FieldValue') . ' = "Pending"');

$db->setQuery($query);
$result = $db->loadColumn();

foreach($result as $value) {
        foreach($value as $key => $data) {
         $cut = substr($data, 6);
         $cut = "Container".$cut;
     }
}
?>

Sie werden bemerken, dass ich substr verwendet habe, um die ersten 6 Buchstaben (Status) aus jedem Ergebnis zu entfernen. Dies dient nur zum Abrufen der verbleibenden Nummer (entweder 1, 2, 3, 4 usw., je nachdem, welcher Status "Ausstehend" ist). Ich habe dann auch "Container" vor jede der verbleibenden Nummern eingefügt, da der "FieldValue", den ich suche, "Container1 bis Container10" ist (abhängig davon, um welches Feld es sich handelt). Denken Sie daran, es wird nur angezeigt, wo der Status "Ausstehend" ist, sodass möglicherweise ein Ergebnis oder 10 Ergebnisse abgerufen werden.

Daher dachte ich, der einfachste Weg wäre, jedem Array-Element das erforderliche Präfix hinzuzufügen. dann wähle ich den "FieldValue" aus der "SubmissionValue" -Spalte aus, wobei der "FieldValue" gleich dem "FieldName" eines der in der vorherigen Abfrage erhaltenen Ergebnisse ist.

Hier ist der Code dafür:

<?php
$query = $db->getQuery(true);
$query->select($db->quoteName(array('FieldValue')));
$query->from($db->quoteName('#__rsform_submission_values'));
$query->where($db->quoteName('FieldName') . ' IN ' . '(' . implode(',', $cut) . ')');

$db->setQuery($query);
$results = $db->loadObjectList();

foreach($results as $value) {
        foreach($value as $key => $data) {
        echo $data."<br />";
     }
}
?>

Ich habe versucht, "loadRow", "loadColumn", "loadResult" usw. zu verwenden, und keiner von ihnen funktioniert. Es heißt, ich habe einen Syntaxfehler (1064), wenn ich die Seite lade.

Ich bin nicht sicher, ob es sich um ein Problem mit "SubmissionId" handelt. Ich weiß jedoch nicht, wie ich die SubmissionId in diese Abfrage einbauen soll, da das Substr sie einfach in der ersten Abfrage entfernt und dann das Präfix davor hinzufügt, was es nicht tun sollte.

Mit anderen Worten:

  • Abfrage 1 ruft alle "Status" -Felder mit dem Wert "Ausstehend" ab.
  • Ich entferne den "Status" aus diesen Feldern, damit nur die Nummer übrig bleibt.
  • Ich füge dann ein Präfix zu diesen Zahlen hinzu, abhängig von dem Feld (das oben in einem Absatz aufgeführt ist).
  • Ich habe nun "Container1" als Ergebnis (abhängig von der Anzahl; 1 - 10).
  • Ich muss dann den "FieldValue" für jedes der Ergebnisse finden.
  • Ich versuche, den Wert $ cut in einem Imploden-Array zu verwenden, aber es funktioniert nicht.
2
MailBlade

Es wird empfohlen, die Anzahl der Aufrufe der Datenbank zu minimieren.

Ihre Logik in Ihren beiden Abfragen kann wie folgt zu einer zusammengefasst werden:

try {
    $db = JFactory::getDbo();
    $query = $db->getQuery(true)
                ->select("a.FieldName, a.FieldValue")
                ->from("#__rsform_submission_values a")
                ->innerJoin("#__rsform_submission_values b ON a.SubmissionId = b.SubmissionId AND a.FieldName = REPLACE(b.FieldName, 'Status', 'Container')")
                ->where(["b.FieldValue = 'Pending'", "b.FieldName LIKE 'Status%'"]);
    $db->setQuery($query);
    echo $query->dump();    // never show to public
    if (!$result = $db->loadAssocList()) {
        echo "No rows found";
    } else {
        echo "<pre>";
            var_export($result);
        echo "</pre>";
    }
} catch (Exception $e) {
    JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error');    // never show to public
}

Ausgabe:

SELECT a.FieldName, a.FieldValue
FROM jos_rsform_submission_values a
INNER JOIN jos_rsform_submission_values b ON a.SubmissionId = b.SubmissionId AND a.FieldName = REPLACE(b.FieldName, 'Status', 'Container')
WHERE b.FieldValue = 'Pending' AND b.FieldName LIKE 'Status%'

array (
  0 => 
  array (
    'FieldName' => 'Container3',
    'FieldValue' => 'KKFU6780793',
  ),
)

Indem Sie die Tabelle mit sich selbst verbinden und festlegen, dass Sie nur an SubmissionId Daten interessiert sind, die mit "Status # = 'Pending'" verknüpft sind, können Sie zwei Fahrten in die Datenbank vermeiden.


Wie für Ihre ursprünglichen Schnipsel ... (die ich nicht empfehlen, dass Sie versuchen, zu retten)

Sie haben Ihre Variable $cut In der Schleife überschrieben (ohne Elemente in ein Array $cut Zu verschieben). Es hätte ungefähr so ​​aussehen müssen:

foreach($result as $value) {
     $cut[] = "Container" . substr($value, 6);
}

In der nächsten Abfrage müssen Sie Ihre Artikel in IN in einfache Anführungszeichen setzen.

"... IN ('" . implode("','", $cut) . "')"

In Bezug auf die Leistung gibt es verschiedene Möglichkeiten, die Abfrage so zu schreiben, dass das gewünschte Ergebnis erzielt wird. Ich weiß jedoch nicht, über wie viele Zeilen Ihr Projekt verfügt, um einen genauen Benchmarking-Test zu starten. (und ich habe ohnehin noch keine Zeit, diesen Service anzubieten)

Hier ist eine weitere Abfrage, die eine gute Leistung erbringen sollte:

SELECT a.SubmissionId, a.FieldName AS ContainerName, a.FieldValue AS ContainerValue
FROM jos_rsform_submission_values a
INNER JOIN (
    SELECT SubmissionId, SUBSTRING(FieldName, 7) AS StatusNum
    FROM jos_rsform_submission_values
    WHERE FieldValue = 'Pending'
      AND FieldName LIKE 'Status%'
) b ON a.SubmissionId = b.SubmissionId AND a.FieldName = CONCAT('Container', b.StatusNum)
2
mickmackusa

Angenommen, dies ist der vollständige Code und das zweite Code-Snippet folgt direkt nach dem ersten:

$db->loadColumn() gibt ein einfaches Array zurück, aber Sie führen geschachtelte foreach Schleifen aus, die bei aktivierter strenger Fehlerberichterstattung zu einer Warnung führen würden:

Warning: Invalid argument supplied for foreach()

Aus diesem Grund lautet die Variable $cutNULL. Sie müssen Zeichenfolgen auch mit $db->quote() maskieren.

Ändern Sie in Ihrem ersten Snippet die Schleifen von foreach wie folgt:

foreach($result as $key => $value) {
    $result[$key] = $db->quote('Container' . substr($value, 6));
}

Und übergeben Sie dann $result Anstelle von $cut An implode() im zweiten Snippet.

0
Sharky