Wie kann ich UNION für 2 Sammlungen verwenden? Oder Sammlungen zusammenführen? (zur Verwendung im Adminhtml-Raster)

7

Zunächst einmal versuche ich Folgendes zu tun:

Holen Sie sich eine Sammlung mit Kunden, die noch keine Bestellungen haben, und Newletters-Abonnenten, die kein Kundenkonto haben.

In MySQL existiert FULL JOIN und FULL OUTER JOIN nicht, daher lautet meine grundlegende SQL-Abfrage:

SELECT 
    `e`.`entity_id`, `e`.`group_id`, `e`.`email`, `salesOrder`.`entity_id` AS `order_id`, `salesRecurringProfile`.`profile_id`, `newsletterSubscriber`.`subscriber_status`, `newsletterSubscriber`.`subscriber_id`, `newsletterSubscriber`.`subscriber_email`, `newsletterSubscriber`.`customer_id` 
FROM 
    `customer_entity` AS `e`
LEFT JOIN 
    `sales_flat_order` AS `salesOrder` ON e.entity_id = salesOrder.customer_id AND salesOrder.status = 'processing'
LEFT JOIN 
    `sales_recurring_profile` AS `salesRecurringProfile` ON e.entity_id = salesRecurringProfile.customer_id AND salesRecurringProfile.state = 'active'
LEFT JOIN 
    `newsletter_subscriber` AS `newsletterSubscriber` ON e.entity_id = newsletterSubscriber.customer_id WHERE (salesOrder.entity_id IS NULL AND salesRecurringProfile.profile_id IS NULL)

UNION   

SELECT 
    `e`.`entity_id`, `e`.`group_id`, `e`.`email`, `salesOrder`.`entity_id` AS `order_id`, `salesRecurringProfile`.`profile_id`, `newsletterSubscriber`.`subscriber_status`, `newsletterSubscriber`.`subscriber_id`, `newsletterSubscriber`.`subscriber_email`, `newsletterSubscriber`.`customer_id` 
FROM 
    `customer_entity` AS `e`
LEFT JOIN 
    `sales_flat_order` AS `salesOrder` ON e.entity_id = salesOrder.customer_id AND salesOrder.status = 'processing'
LEFT JOIN 
    `sales_recurring_profile` AS `salesRecurringProfile` ON e.entity_id = salesRecurringProfile.customer_id AND salesRecurringProfile.state = 'active'
RIGHT JOIN 
    `newsletter_subscriber` AS `newsletterSubscriber` ON e.entity_id = newsletterSubscriber.customer_id WHERE (salesOrder.entity_id IS NULL AND salesRecurringProfile.profile_id IS NULL)

Ich versuche dies zu transponieren, indem ich Sammlungen verwende, um es mit einem Raster zu verwenden:

    $customersSubscribersLeftJoin = Mage::getResourceModel('customer/customer_collection');
    $customersSubscribersLeftJoin->getSelect()
        ->reset(Zend_Db_Select::COLUMNS)
        ->columns(array(
            'entity_id', 
            'group_id',
            'email'
        ))
        ->joinLeft(array('salesOrder' => $resource->getTableName('sales/order')), 'e.entity_id = salesOrder.customer_id AND salesOrder.status = \'' . Mage_Sales_Model_Order::STATE_PROCESSING .  '\'', array(
            'entity_id' => 'salesOrder.entity_id AS order_id'
        ))
        ->joinLeft(array('salesRecurringProfile' => $resource->getTableName('sales/recurring_profile')), 'e.entity_id = salesRecurringProfile.customer_id AND salesRecurringProfile.state = \'' . Mage_Sales_Model_Recurring_Profile::STATE_ACTIVE .  '\'', array(
            'profile_id'    => 'profile_id'
        ))
        ->joinLeft(array('newsletterSubscriber' => $resource->getTableName('newsletter/subscriber')), 'e.entity_id = newsletterSubscriber.customer_id', array(
            'subscriber_status' => 'subscriber_status',
            'subscriber_id'     => 'subscriber_id',
            'subscriber_email'  => 'subscriber_email',
            'customer_id'       => 'customer_id'
        ))
        ->reset(Zend_Db_Select::WHERE)
        ->where('salesOrder.entity_id IS NULL AND salesRecurringProfile.profile_id IS NULL');

    $customersSubscribersRightJoin = Mage::getResourceModel('customer/customer_collection');
    $customersSubscribersRightJoin->getSelect()
        ->reset(Zend_Db_Select::COLUMNS)
        ->columns(array(
            'entity_id', 
            'group_id',
            'email'
        ))
        ->joinLeft(array('salesOrder' => $resource->getTableName('sales/order')), 'e.entity_id = salesOrder.customer_id AND salesOrder.status = \'' . Mage_Sales_Model_Order::STATE_PROCESSING .  '\'', array(
            'entity_id' => 'salesOrder.entity_id AS order_id'
        ))
        ->joinLeft(array('salesRecurringProfile' => $resource->getTableName('sales/recurring_profile')), 'e.entity_id = salesRecurringProfile.customer_id AND salesRecurringProfile.state = \'' . Mage_Sales_Model_Recurring_Profile::STATE_ACTIVE .  '\'', array(
            'profile_id'    => 'profile_id'
        ))
        ->joinRight(array('newsletterSubscriber' => $resource->getTableName('newsletter/subscriber')), 'e.entity_id = newsletterSubscriber.customer_id', array(
            'subscriber_status' => 'subscriber_status',
            'subscriber_id'     => 'subscriber_id',
            'subscriber_email'  => 'subscriber_email',
            'customer_id'       => 'customer_id'
        ))
        ->reset(Zend_Db_Select::WHERE)
        ->where('salesOrder.entity_id IS NULL AND salesRecurringProfile.profile_id IS NULL');

Wie kann ich aus diesen beiden Sammlungen eine UNION erstellen oder sie in einem einzigen Aufruf nur mit der ersten Sammlung erstellen?

Vielen Dank im Voraus


BEARBEITEN:

Durch die Nutzung :

        $customersSubscribersLeftJoin->getSelect()
        ->union(
            array(
                $customersSubscribersRightJoin->getSelect()
            )
        );

Die angegebene Abfrage lautet:

   SELECT 
    `e`.`entity_id`, `e`.`group_id`, `e`.`email`, `salesOrder`.`entity_id` AS `order_id`, `salesRecurringProfile`.`profile_id`, `newsletterSubscriber`.`subscriber_status`, `newsletterSubscriber`.`subscriber_id`, `newsletterSubscriber`.`subscriber_email`, `newsletterSubscriber`.`customer_id`SELECT `e`.`entity_id`, `e`.`group_id`, `e`.`email`, `salesOrder`.`entity_id` AS `order_id`, `salesRecurringProfile`.`profile_id`, `newsletterSubscriber`.`subscriber_status`, `newsletterSubscriber`.`subscriber_id`, `newsletterSubscriber`.`subscriber_email`, `newsletterSubscriber`.`customer_id` 
FROM 
    `customer_entity` AS `e`
LEFT JOIN 
    `sales_flat_order` AS `salesOrder` ON e.entity_id = salesOrder.customer_id AND salesOrder.status = 'processing'
LEFT JOIN 
    `sales_recurring_profile` AS `salesRecurringProfile` ON e.entity_id = salesRecurringProfile.customer_id AND salesRecurringProfile.state = 'active'
RIGHT JOIN 
    `newsletter_subscriber` AS `newsletterSubscriber` ON e.entity_id = newsletterSubscriber.customer_id 
WHERE 
    (salesOrder.entity_id IS NULL AND salesRecurringProfile.profile_id IS NULL) 
FROM 
    `customer_entity` AS `e`
LEFT JOIN 
    `sales_flat_order` AS `salesOrder` ON e.entity_id = salesOrder.customer_id AND salesOrder.status = 'processing'
LEFT JOIN 
    `sales_recurring_profile` AS `salesRecurringProfile` ON e.entity_id = salesRecurringProfile.customer_id AND salesRecurringProfile.state = 'active'
LEFT JOIN 
    `newsletter_subscriber` AS `newsletterSubscriber` ON e.entity_id = newsletterSubscriber.customer_id 
WHERE 
    (salesOrder.entity_id IS NULL AND salesRecurringProfile.profile_id IS NULL)

Was ist eindeutig nicht das, was wir wollen, wenn wir die beiden Fragen vereinen, irgendwelche Ideen?

Thomas Seres
quelle

Antworten:

3

Angenommen, die beiden Sammlungen sind korrekt und alles, was Sie tun müssen, ist, die beiden Sätze zu verbinden. Von einem rein hypothetischen Standpunkt aus könnten Sie Folgendes versuchen:

$customersSubscribersLeftJoin
    ->getSelect()
    ->union(
        array(
            $customersSubscribersLeftJoin->getSelect()
        )
    );

Ich vermute jedoch, dass Sie Schwierigkeiten mit der resultierenden Sammlung haben würden. Sie würden wahrscheinlich so etwas wie "Artikel mit dieser ID existiert bereits" erhalten, und das setzt voraus, dass es sogar funktioniert, was ich nicht wirklich getestet habe.

Peter O'Callaghan
quelle
Hallo ! Vielen Dank, dass Sie sich die Zeit genommen haben, um zu antworten! Ich teste auf diese Weise, um die Vereinigung durchzuführen. Das Problem ist, dass die letzte von dieser gestellte Abfrage nicht "UNION" hinzufügt. Es löscht die Auswahl aus der zweiten Abfrage und verkettet das "FROM" und die Joins! Wirklich komisch
Thomas Seres
Für weitere Informationen bearbeite ich einfach meinen Beitrag und stelle die Abfrage der Gewerkschaft
Thomas Seres
1
Es scheint, dass Zend_Db_Select::uniondies nicht so funktioniert, wie Sie es vielleicht erwarten. Ich denke, Sie erhalten die richtige Abfrage, für die Sie eine Instanz benötigen, Zend_Db_Selectund übergeben sie dann getSelect()aus beiden Sammlungen als Array. Ich bin mir jedoch nicht sicher, wie dies in Bezug auf Magento funktionieren würde, da Sie anscheinend das zurückgegebene Auswahlobjekt als Auswahlobjekt in der Sammlung festlegen müssen, was meines Wissens nicht möglich ist.
Peter O'Callaghan
3

Sie müssen Ihre Auswahl klonen und zurücksetzen.

$customersLeftSelect = clone $customersSubscribersLeftJoin->getSelect();
$customersSubscribersLeftJoin
    ->getSelect()
    ->reset()
    ->union(
        array(
            $customersLeftSelect,
            $customersSubscribersRightJoin
        )
    );

So hat es bei mir funktioniert.

Tom ist
quelle
Danke, es funktioniert für mich. Ich gebe Ihnen ein Beispiel, bitte schauen Sie sich diese $ userCollection = clone $ collection-> getSelect () an. UNION: $ myresult = $ userCollection-> reset () -> union (Array ($ adminCollection-> getSelect () -> __ toString (), $ collection-> getSelect () -> __ toString ()); UNION ALL: $ myresult = $ userCollection-> reset () -> union (Array ($ adminCollection-> getSelect () -> __ toString (), $ collection-> getSelect () -> __ toString ()), \ Magento \ Framework \ DB \ Select :: SQL_UNION_ALL);
Renga
1
$selectFoo = Mage::getResourceModel('model/foo')->getSelect();
$selectBar= Mage::getResourceModel('model/bar')->getSelect();

$mergedFooBar = $selectFoo->union(array($selectBar));
TBI Infotech
quelle