Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return distinct values in a JSON_ARRAYAGG

Tags:

oracle

plsql

So I'm attempting to place the results of a distinct, single-column query into a JSON array so it can be used on my web server. I have it set up something like this:

SELECT JSON_OBJECT(
  'ArrayKey' VALUE JSON_ARRAYAGG( col ) 
) AS jsonResult
FROM(SELECT DISTINCT column_name AS col
       FROM tbl_name);

However, when this query returns results, the array it generates in JSON contains all values from my column and ignores the DISTINCT clause in the subquery somehow. Whenever I get rid of the JSON_ARRAYAGG clause and output the results directly, the result are unique, but somehow the command is ignored when I add it back in. I've also attempted to place the DISTINCT clause inside the JSON_ARRAYAGG as well, like so:

SELECT JSON_OBJECT(
  'ArrayKey' VALUE JSON_ARRAYAGG( DISTINCT col ) 
) AS jsonResult
FROM(SELECT DISTINCT column_name AS col
       FROM tbl_name);

to no avail. Does anyone know what's going wrong in my code that's causing the array to output all values instead of distinct ones?

like image 884
jwas Avatar asked Apr 17 '19 21:04

jwas


Video Answer


2 Answers

Interesting... Looks like a bug to me. The optimizer seems to push down too eagerly.

As workaround you can use the NO_MERGE hint on the subquery.

SELECT /*+NO_MERGE(x)*/
      json_object('ArrayKey'
                  VALUE json_arrayagg(column_name)) jsonresult
      FROM (SELECT DISTINCT
                   column_name
                   FROM tbl_name) x;

A CTE and a MATERIALIZE hint seem to work too.

WITH cte
AS
(
SELECT /*+MATERIALIZE*/ 
       DISTINCT
       column_name
       FROM tbl_name
)
SELECT json_object('ArrayKey'
                   VALUE json_arrayagg(column_name)) jsonresult
       FROM cte;

db<>fiddle

like image 141
sticky bit Avatar answered Oct 13 '22 17:10

sticky bit


This was a bug, we fixed it. You can try it out on live SQL

create table tbl_name (column_name number);
insert into tbl_name values(1);
insert into tbl_name values(1);
insert into tbl_name values(2);


SELECT JSON_OBJECT(
'ArrayKey' VALUE JSON_ARRAYAGG( col ) 
) AS jsonResult
FROM(SELECT DISTINCT column_name AS col
     FROM tbl_name);

{"ArrayKey" : [1,2]}

The bug is Bug 27757725 - JSON GENERATION AGGREGATION FUNCTIONS IGNORE DISTINCT you can request a backport from Oracle Support Services

like image 39
Beda Hammerschmidt Avatar answered Oct 13 '22 15:10

Beda Hammerschmidt