Sample Header Ad - 728x90

Postgres: How to select rows, grouping by rows with same column field into one row, with pagination

0 votes
0 answers
43 views
I've a table, with fields like | id | batchId | senderId | recipientId| | -------- | -------------- | ------- |------| | uuid1 | uuid | uuid5 | uuid7 | | uuid2 | uuid | uuid5 | uuid8 | | uuid3 | uuid2 | uuid6 | uuid9 | I need to select rows with pagination, but handling rows with same batchId as one row, and joining it into array, like | batchId | senderId | recipientIds| | -------- | -------------- | ------- | {uuid} | {uuid5} | {uuid7, uuid8} {uuid2} | {uuid6}| {uuid9} It's a simplified version of table Currently I'm doing it with query but it's quite heavy, and takes like 5 second to execute on db about 2m records. I'm using indexes, but that doesn't help. Here below is query
SELECT "sendData"."id"                                                                   AS "id"
     , "sendData"."pictureLink"                                                          AS "pictureLink"
     , "sendData"."isPaid"                                                               AS "isPaid"
     , "sendData"."createdAt"                                                            AS "createdAt"
     , "sendData"."updatedAt"                                                            AS "updatedAt"
     , "sendData"."senderId"                                                             AS "senderId"
     , "sendData"."recipient"                                                            AS "recipient"
     , "sendData"."isAnonymous"                                                          AS "isAnonymous"
     , "sendData"."recipientAccountId"                                                   AS "recipientAccountId"
     , "sendData"."senderAccountId"                                                      AS "senderAccountId"
     , "sendData"."senderPhotoUrl"                                                       AS "senderPhotoUrl"
     , "sendData"."recipientPhotoUrl"                                                    AS "recipientPhotoUrl"
     , "sendData"."isDeleted"                                                            AS "isDeleted"
     , "sendData"."oldCategory"                                                          AS "oldCategory"
     , "sendData"."batchId"                                                              AS "batchId"
     , CONCAT("sender"."firstName", ' ', "sender"."lastName", ' ', "sender"."patronymic") AS sender
     , json_build_object('id', "category"."id"
    , 'createdAt', "category"."createdAt"
    , 'updatedAt', "category"."updatedAt"
    , 'name', "category"."name"
    , 'baseName', "category"."baseName"
    , 'emojiId', "category"."emojiId"
    , 'text', "category"."text"
    , 'isVisible', "category"."isVisible"
    , 'isLocked', "category"."isLocked"
    , 'widgetText', "category"."widgetText"
    , 'emoji', json_build_object('id', "emoji"."id"
                             , 'createdAt', "emoji"."createdAt"
                             , 'updatedAt', "emoji"."updatedAt"
                             , 'unicode', "emoji"."unicode")
       )                                                                                  as category

     , (SELECT COALESCE(json_agg(
                                json_build_object(
                                        'id', "reaction"."id"
                                    , 'userAccountId', "reaction"."userAccountId"
                                    , 'sendDataId', "reaction"."sendDataId"
                                    , 'type', "reaction"."type"
                                )
                        ), '[]')
        FROM sendData_reactions as reaction
        where reaction."sendDataId" = ANY (ids))                                         as reactions
     , "recipientIds"
     , "recipients"
     , "ids"
FROM sendData as sendData
          JOIN (SELECT "batchId",
                      "senderId",
                      json_agg(tableName."recipientAccountId") AS "recipientIds",
                      json_agg(tableName."recipient")          AS "recipients",
                      array_agg(tableName.id)                  as "ids",
                      min(tableName.id::text)::uuid            as "id",
                      tableName."createdAt"
               FROM sendData as tableName
                        LEFT JOIN "user" as "sender"
                                  ON "sender"."id" = tableName."senderId"
                 AND "sender"."groupId" = 'id-here'
                 and sender."deletedAt" is null
               WHERE tableName."isDeleted" = false
                 AND "sender"."groupId" = 'id-here'
                 and sender."deletedAt" is null
                 AND tableName."isAnonymous" = false
               GROUP BY "batchId", tableName."createdAt", "senderId"
               ORDER BY tableName."createdAt" DESC
               OFFSET 0 LIMIT 100) as groupped
              ON sendData."id" = groupped."id"
                  AND sendData."createdAt" = groupped."createdAt"
         LEFT JOIN "user" as "sender"
                   ON "sender"."id" = sendData."senderId"
         LEFT JOIN "sendData_categories" as category
                   ON "category"."id" = sendData."categoryId"
         LEFT JOIN "sendData_categories_emoji" as "emoji"
                   ON "emoji"."id" = "category"."emojiId"
WHERE sendData."groupId" = 'uuid'
  AND sendData."isAnonymous" = false
  AND sendData."isDeleted" = false
ORDER BY sendData."createdAt" DESC
OFFSET 0 LIMIT 10;
Asked by Sendoff74 (1 rep)
Nov 15, 2024, 03:09 AM
Last activity: Nov 15, 2024, 09:06 AM