1
votes

I have a PostgreSQL database containing a table test_table with individual records. First column is a simple store_id, second column meausurement is a nested json.

store_id | measurement
----------------------
0        | {...}

The format of the measurement column is as follows:

{
    'file_info': 'xxxx', 
    'data': {
        'contour_data': {
            'X': [-97.0, -97.0, -97.0, -97.0, -97.0, -97.0],
            'Y': [-43.0, -41.0, -39.0, -39.0, -38.0, -36.0]
        }
    }
}

I would like to plot Y vs. X in a scatter plot in Tableau. Therefore I connected the database successfully with the PostgreSQL connector of Tableau. From this page I learned, that I have to use Custom SQL queries to extract data from the json object, since Tableau doesn't directly support the json datatype of Postgres. I tried already the following Custom SQL Query in Tableau:

select
    store_id as store_id,
    measurement#>>'{data, contour_data, X}' as contour_points_x,
    measurement#>>'{data, contour_data, Y}' as contour_points_y
from test_table

which successfully extracts the two arrays to two new columns contour_points_x and contour_points_y. However both new columns are in Tableau of type string, so I cannot use them as data source for a plot.

How do I have to adjust the Custom SQL query to make the data arrays plottable in a Tableau scatter plot?

2

2 Answers

2
votes

Looks like you need to split the columns. Check this https://help.tableau.com/current/pro/desktop/en-us/split.htm

EDIT - the linked approach works when you can reliably assume an upper bound for the number of points in each list. One way to split arbitrarily sized lists is described here https://apogeeintegration.com/blog/apogee-busts-out-multi-value-cells-using-tableau-prep-builder

0
votes

The answer is a concatenation of several functions and/or syntax operations. One has to

  • use the #> operator to dig in the json and return it as json type (not as text type as >># does).
  • use json_array_elements_text() to expand the json to a set of text.
  • use type cast operator :: to convert text to float
/* custom SQL Query in Tableau */
select 
    store_id as store_id,
    json_array_elements_text(measurement#>'{data, contour_data, X}')::float as contour_points_x,
    json_array_elements_text(measurement#>'{data, contour_data, Y}')::float as contour_points_y,
from test_table

Both resulting columns appear in a Tableau Sheet now as discrete measures. Changing to discrete dimensions allows to plot contour_points_y vs. contour_points_x as desired.