Score:1

How to remove duplicates in view... the return

sa flag

I know that this question turn around in Drupal answers but I couldn't get a working answer for my use case.

Here it is: I have a view which is producing duplicate results (and I understand why) but I couldn't find a way to remove them in the hook views_query_alter

This view is requesting nodes with some filters and a left join (Require this relationship) on a field wich contains references to paragraphs (node__field_aw_agenda). This is this relationship which produce the duplicates.

SELECT "node_field_data"."nid" AS "nid", "node_field_data"."langcode" AS "node_field_data_langcode", DATE_FORMAT(paragraphs_item_field_data_node__field_aw_agenda__paragraph__field_agenda_date.field_agenda_date_value, '%Y%m%d') AS "paragraphs_item_field_data_node__field_aw_agenda__paragraph_", MIN(node_field_data.nid) AS "nid_2", MIN(paragraphs_item_field_data_node__field_aw_agenda.id) AS "paragraphs_item_field_data_node__field_aw_agenda_id"
FROM
{node_field_data} "node_field_data"
LEFT JOIN {node__field_aw_agenda} "node__field_aw_agenda" ON node_field_data.nid = node__field_aw_agenda.entity_id AND node__field_aw_agenda.deleted = '0'
INNER JOIN {paragraphs_item_field_data} "paragraphs_item_field_data_node__field_aw_agenda" ON node__field_aw_agenda.field_aw_agenda_target_id = paragraphs_item_field_data_node__field_aw_agenda.id
LEFT JOIN {node__field_aw_prod_state} "node__field_aw_prod_state" ON node_field_data.nid = node__field_aw_prod_state.entity_id AND node__field_aw_prod_state.deleted = '0'
LEFT JOIN {node__field_aw_images} "node__field_aw_images" ON node_field_data.nid = node__field_aw_images.entity_id AND node__field_aw_images.deleted = '0'
LEFT JOIN {paragraph__field_agenda_date} "paragraphs_item_field_data_node__field_aw_agenda__paragraph__field_agenda_date" ON paragraphs_item_field_data_node__field_aw_agenda.id = paragraphs_item_field_data_node__field_aw_agenda__paragraph__field_agenda_date.entity_id AND paragraphs_item_field_data_node__field_aw_agenda__paragraph__field_agenda_date.deleted = '0'
WHERE ("node_field_data"."status" = '1') AND ("node_field_data"."type" IN ('aw_audiovisu', 'aw_scenicarts')) AND ("node__field_aw_prod_state"."field_aw_prod_state_value" IN ('prem', 'play')) AND ("node_field_data"."langcode" IN ('fr')) AND ("node__field_aw_images"."field_aw_images_target_id" IS NOT NULL)
GROUP BY "node_field_data"."nid", "paragraphs_item_field_data_node__field_aw_agenda__paragraph_", "node_field_data_langcode"
ORDER BY "paragraphs_item_field_data_node__field_aw_agenda__paragraph_" DESC

As you can see, there is a GROUP BY term with several fields in it. This GROUP BY term is added in the following hook

function mymodule_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  $view_id = $view->id();
  $display_id = $view->current_display;
  if (($view_id == 'my_view') && ($display_id == 'my_display_id')) {
    $query->addField('node_field_data', 'nid', 'nid', [
      'function' => 'groupby',
    ]);
    $query->groupby = ['node_field_data.nid'];
  }
}

Note that this hook is adding only one GROUP BY field ("node_field_data"."nid"), I don't know how this lead to add the other fields ("paragraphs_item_field_data_node__field_aw_agenda__paragraph_", "node_field_data_langcode")

Please do not provide me a solution with hook_views_pre_render() as I am looking for a generic SQL solution

As requested, here is a screenshot of the view UI

View UI

No Sssweat avatar
ua flag
Have you tried turning on distinct in the [query settings](https://i.stack.imgur.com/jGTwi.png)?
Baud avatar
sa flag
Yes, no result with distinct ON.
mx flag
Have you tried Aggregation? That is usually the way to deal with Relationship duplicates, you find what exactly is causing the duplicates, it might be a field that is using the Relationship, and change the Aggregation setting on it to Entity ID instead of Value, or something similar. Your example isn't very readable from Drupal Views perspective, it requires SQL debugging.
Baud avatar
sa flag
I have tried aggregation without luck: I have tested many options on several fields. The main question is why in `views_query_alter` I set only one field in the `GroupBy` clause but at the end there are multiple fields in the clause.
Score:0
US flag
user106880

To remove unnecessary GROUP BY statements added to a query, you can use the unset() function in your hook implementation to remove the unwanted groupings. Here's an updated version of your code that removes the unwanted GROUP BY fields:

function mymodule_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  $view_id = $view->id();
  $display_id = $view->current_display;
  if (($view_id == 'my_view') && ($display_id == 'my_display_id')) {
    $query->addField('node_field_data', 'nid', 'nid', [
      'function' => 'groupby',
    ]);
    $query->groupby = ['node_field_data.nid'];

    // Remove unwanted GROUP BY fields
    unset($query->groupby['paragraphs_item_field_data_node__field_aw_agenda__paragraph_']);
    unset($query->groupby['node_field_data_langcode']);
  }
}
Baud avatar
sa flag
Thank you, but unfortunately in this hook, the `$quey->groupby` array is not yet populated by the unwanted groupings. Note also that the line `$query->groupby = ['node_field_data.nid'];` already ensures that there is only one grouping in the `groupby` array
liquidcms avatar
us flag
Good question. In many simpler cases the addField and addGroupBy works; but in some cases extra group by's get added for no apparent reason which break the group fix.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.