0

I currently have a logs table which has the following rows which use the same order_id:

log_id order_id user action
2410 1001318004 test1 Declined
2409 1001318004 test1 Declined

Inside my app/code/Vendor/Module/Model/ResourceModel/OrderTable/Collection.php class file I have the following method to set the collection results:

protected function _initSelect()
    {
        $this->getSelect()->from(['main_table' => $this->getMainTable()]);

        $this->getSelect()
            ->joinLeft(
                ['logs' => $this->getTable('logs')],
                'main_table.increment_id = logs.order_id',
                ['*','customer_name'=>'CONCAT_WS(" ",main_table.customer_firstname,main_table.customer_lastname)']
            );

        return $this->filterOrders();
    }

where main_table references the sales_order table.

but when I view the results in the admin I get the following error:

Item (Magento\Framework\View\Element\UiComponent\DataProvider\Document) with the same ID "1557472" already exists.

The 1557472 refers to the entity ID matching the order for the 1001318004 increment ID.

What I'm looking for, is a way to only get the latest row if there are duplicates in the results.

Cheers guys

13
  • If this one is your log table 'innox_prescriber_logs' then try like this " main_table.increment_id = innox_prescriber_logs.order_id ". and let me know it is working or not Commented Sep 21, 2021 at 17:03
  • Hi Viru, sorry about that, just realised that was the incorrect code I previously had in there, but I have updated it now so could you please take another look if you wouldn't mind?
    – SNAFU
    Commented Sep 21, 2021 at 17:07
  • can you print your query which is created collection and check what is your query. use this to print query magento.stackexchange.com/questions/166536/… Commented Sep 21, 2021 at 17:13
  • Okey dokey, here is the output from the select query: "SELECT `main_table`.*, `logs`.*, CONCAT_WS(" ",main_table.customer_firstname,main_table.customer_lastname) AS `customer_name` FROM `sales_order` AS `main_table` LEFT JOIN `logs` ON main_table.increment_id = logs.order_id" but what I need, is for it to return only the latest rows for duplicate entries.
    – SNAFU
    Commented Sep 21, 2021 at 17:28
  • you can use for return only $this or $this->getSelect() and check. Commented Sep 21, 2021 at 17:34

1 Answer 1

1

Ok, so after a long time of troubleshooting this, I have finally resolved it. So here is the solution for anyone else who encounters a similar problem.

The initial method:

protected function _initSelect()
    {
        $this->getSelect()->from(['main_table' => $this->getMainTable()]);

        $this->getSelect()
            ->joinLeft(
                ['logs' => $this->getTable('logs')],
                'main_table.increment_id = logs.order_id',
                ['*','customer_name'=>'CONCAT_WS(" ",main_table.customer_firstname,main_table.customer_lastname)']
            );

        return $this->filterOrders();
    }

the new method:

protected function _initSelect()
    {
        $this->getSelect()->from(['main_table' => $this->getMainTable()]);

        $connection = $this->getConnection();

        // first we create a query which gets the max value for the row id, and then groups the results on order_id 
        $groupedResults = $connection->select();
        $groupedResults
            ->from(['logs_grouped' => 'logs'])
            ->reset($groupedResults::COLUMNS)
            ->columns(
                [
                    'max_id' => new \Zend_Db_Expr("max(`logs_grouped`.`log_id`)"),
                ]
            )
            ->group('order_id');

        // we create another query which will match the row id values, with the max id values from our grouped set, giving us the latest entries from the duplicates
        $logs = $connection->select();
        $logs
            ->from(['logs' => 'logs'])
            ->reset($logs::COLUMNS)
            ->columns(
                '*'
            )->joinInner(
                ['logs_grouped' => $groupedResults],
                'logs.log_id = logs_grouped.max_id'
            );

        // finally, we left join our new $logs table to the main table (in this case the sales_order table)
        $this->getSelect()
            ->joinLeft(
                ['logs' => $logs],
                'main_table.increment_id = logs.order_id',
                ['*','customer_name'=>'CONCAT_WS(" ",main_table.customer_firstname,main_table.customer_lastname)']
            );

        return $this;
    }

so instead of:

log_id order_id user action
2410 1001318004 test1 Declined
2409 1001318004 test1 Declined

we now get:

log_id order_id user action
2410 1001318004 test1 Declined

giving us the row with the latest id :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.