Combining mulitple arrays as conditions within CASE structure

Hi Dear Experts, I am having almost zero experience with Couchbase. I am trying to make a query on the following sample document in Couchbase:

[
  {
    "bucket": {
      "customerid": 123456,
      "ticket": [
        {
          "creationDate": "2023-11-08T07:31:47.077Z",
          "caseAction": {
            "id": "11",
            "type": "Complaint",
            "reason": "Any"
          },
          "status": {
            "state": "Active"
          },
        },
		{
          "creationDate": "2023-11-07T07:31:47.077Z",
          "caseAction": {
            "id": "11",
            "type": "Complaint",
            "reason": "Any"
          },
          "status": {
            "state": "In Progress"
          },
        },
		{
          "creationDate": "2023-11-06T07:31:47.077Z",
          "caseAction": {
            "id": "11",
            "type": "Request",
            "reason": "Any"
          },
          "status": {
            "state": "Active"
          },
        },
        {
          "creationDate": "2023-11-01T09:40:27.215Z",
          "caseAction": {
            "id": "19",
            "name": "Request",
            "reason": "no reason"
          },
          "status": {
            "state": "Closed"
          },
          "statusDate": "2023-11-30T09:57:03.704Z",
          "validFor": {
            "endDateTime": "2023-11-30T09:57:03.244Z",
            "startDateTime": "2023-11-15T09:40:27.212Z"
          }

  }
]
````Preformatted text`

The equivalent of the query in Oracle or PostgreSQL is like this: 
select customer_id,     
       sum(case
             when name = 'Request' and reason = 'Any' then power(2, 0)
             when name = 'Complaint' and reason = 'Any' then power(2, 1)
             else 0
           end) long_ActiveCases
  from cases
 where state in ('Active','In Progress')
 group by customer_id

The output is for example 123456,3

For some reason unnest doesn't work, using ARRAY is working, but here I need to use under 'ticket' two subarrays for caseStatus to check name and reason, then status for state Active or In Progress  Then use POWER and CASE, which I checked already do exist in N1QL . But don't have a clue how to combine all of those. In RDBMS it is clear, but here :slightly_smiling_face:

How were you attempting UNNESTing ?

UNNEST flattens the array into individual documents, then you use it as if it was a flat stream.

e.g. using your example data:

cbq> SELECT b.customerid, t
   2 FROM `bucket` b
   3 UNNEST ticket t
   4 WHERE b.customerid = 123456
   5 ;
{
    "requestID": "0f3ff8f6-c449-4efe-b528-b9ec7eb2e0a6",
    "signature": {
        "customerid": "json",
        "t": "json"
    },
    "results": [
    {
        "customerid": 123456,
        "t": {
            "caseAction": {
                "id": "11",
                "reason": "Any",
                "type": "Complaint"
            },
            "creationDate": "2023-11-08T07:31:47.077Z",
            "status": {
                "state": "Active"
            }
        }
    },
    {
        "customerid": 123456,
        "t": {
            "caseAction": {
                "id": "11",
                "reason": "Any",
                "type": "Complaint"
            },
            "creationDate": "2023-11-07T07:31:47.077Z",
            "status": {
                "state": "In Progress"
            }
        }
    },
...

So your statement becomes:

SELECT b.customerid,     
       sum(CASE
             WHEN t.caseAction.type = 'Request' AND t.caseAction.reason = 'Any' THEN power(2, 0)
             WHEN t.caseAction.type = 'Complaint' AND t.caseAction.reason = 'Any' THEN power(2, 1)
             ELSE 0
           END) long_ActiveCases
FROM `bucket` b
UNNEST ticket t
WHERE t.status.state IN ['Active','In Progress']
GROUP BY b.customerid

Note:

Also, based on your example data:

  • “customerid” and not “customer_id” is the field name
  • “type” and not “name” compared with ‘Request’ & ‘Complaint’ in the CASE statement
    • the resulting “long_ActiveCases” is not 3 but 5:
      • the first ticket is ‘Complaint’ + ‘Any’ and state is ‘Active’
        • add power(2,1), i.e. 2
      • the second ticket is ‘Complaint’ + ‘Any’ and state is ‘In Progress’
        • add power(2,1), i.e. 2
      • the third is ‘Request’ + ‘Any’ and state is 'Active
        • add power(2,0), i.e. 1
      • the fourth is ‘Request’ + ‘no reason’ and state is ‘Closed’
        • not included
      • The result is:
        • 2 + 2 + 1 = 5

If you have a single document per customer then you could also write it as:

SELECT b.customerid,     
       array_sum(ARRAY CASE
                         WHEN v.caseAction.type = 'Request' AND v.caseAction.reason = 'Any' THEN power(2, 0)
                         WHEN v.caseAction.type = 'Complaint' AND v.caseAction.reason = 'Any' THEN power(2, 1)
                         ELSE 0
                       END
                 FOR v IN b.ticket
                 WHEN v.status.state IN ['Active','In Progress']
                 END
                ) long_ActiveCases
FROM `bucket` b

avoiding the UNNESTing.

With multiple customer documents you could wrap this to aggregate:

SELECT a.customerid, SUM(a.long_ActiveCases) long_ActiveCases
FROM
(
   SELECT ... -- using array_sum()
) AS a
GROUP BY a.customerid

HTH.

1 Like

Thanks a lot!! This really helped in generating expected results, had to tune something but that is related to data, the solution provided worked perfectly!!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.