How to populate a Tree display from a query

Hello!

image

I do have a query that gives me data like this:
image

I would like if possible to bind this data to my tree view but I don´t know where to bind it. Should I use a change script?
SOLICITANTE would be the first folder level,
DESCRIPCION should be the child level, and
NUMERO PETICION the grandchild level

Tree data doesn't necessarily display well in a database format.

You can populate most if not all controls by building the json in a script transform. You could put a binding on your the "items" property that triggers when your data changes. Then you put a script transform on that that builds the json for your tree.

You can copy the items property and paste it into a text editor to get an idea what the json looks like. That's usually my first step if I'm building the json for something in a script transform because it's quicker than looking up documentation (for me).

You may want to consider organizing your data based on the order it is used. If you're in MS SQL, consider using a recursive CTE and consider putting it in a stored procedure to compile the execution plan. I'm told that named queries also compile the execution plan but I haven't benchmarked that to know if it's the same thing that happens when you declare a stored procedure. I typically use stored procedures for anything that could have a significant execution time.

2 Likes

Thank you Steve, that´s the point, convert the data into a Json.

Bind the query to the props.items of the Tree

image

Then used Transform Script using Jython on the query and organizing the hierarchy like:

def transform(self, value, quality, timestamp):
  
    raw_data = value
    

    if raw_data is None or raw_data.getRowCount() == 0:
        return []  

    # Initialize a dictionary to hold the hierarchical data by SOLICITANTE
    hierarchy = {}

    # Iterate through each row in the dataset
    for row in range(raw_data.getRowCount()):
        solicitante = raw_data.getValueAt(row, 2)  # SOLICITANTE at index 2
        descripcion = raw_data.getValueAt(row, 0)  # DESCRIPCION at index 0
        numero_peticiones = raw_data.getValueAt(row, 1)  # NUMERO_PETICIONES at index 1

        # If the SOLICITANTE (parent) is not in the hierarchy yet, add it
        if solicitante not in hierarchy:
            hierarchy[solicitante] = {
                "label": solicitante,
                "expanded": False,
                "items": []  # This will hold DESCRIPCION children
            }

        # Add DESCRIPCION (child) with NUMERO_PETICIONES (grandchild)
        descripcion_item = {
            "label": descripcion,
            "expanded": False,
            "items": [
                {
                    "label": "NUMERO PETICIONES: {}".format(numero_peticiones),
                    "expanded": False
                }
            ]
        }

        # Append the DESCRIPCION item to the SOLICITANTE's items
        hierarchy[solicitante]["items"].append(descripcion_item)

    # Convert the hierarchy dictionary to a list of dictionaries
    json_list = list(hierarchy.values())

   
    return json_list

Result:
image

I guess would be similar aproach to populate bar charts from querys.

A lot of times you can set the return format to json. Play around with return format and see if it's what you are looking for.

1 Like

Thanks Steve, I trying this out for a charts and is working great! I was using datasets and going crazy because didn´t work.
Just what i was looking for!


imagea

I assure you I have had the same problem in the past. Glad I could help.

1 Like

I use something like this to build this kind of tree:

tree = []
for row in data:
	folder = tree
	for val in [row['SOLICITANTE'], row['DESCRIPCION']]:
		try:
			folder = next(f['items'] for f in folder if f['label'] == val)
		except StopIteration:
			folder.append(
				{
					'label': val,
					'expanded': False,
					'items': []
				}
			)
			folder = folder[-1]['items']
	folder.append(
		{
			'label': "NUMERO PETICIONES: {}".format(row['NUMERO PETICION']),
			'expanded': False
		}
	)

Maybe it helps, maybe it doesn't. Do with that what you want.

2 Likes

Yes, this code to build trees works great, it´s dynamic no matter the deep of the hierarchy and sure faster.
Thanks Pascal!

Your code:
image

the code I was using:
image

Now I will have to sum them and show one unique result, but that´s another story.

2 Likes

What do you mean, sum them ?
Do you want to sum the "numero peticiones" ?

1 Like

yep, I think I will have to do that to show the totals

For example, here:
image

You'd want to have

AREAS
|-- CON_ASTRAS
    |-- NUMERO PETICIONES: 3

That's it ?

1 Like

Yes

Do that in the query then.
group by SOLICITANTE and DESCRIPCION and select sum(numero peticion)

1 Like

Ok, got a solution, thanks Pascal

def transform(self, value, quality, timestamp):

   
    raw_data = value

   
    if raw_data is None or raw_data.getRowCount() == 0:
        return []  # Return an empty list if no data is available

 
    tree = []


    for row in range(raw_data.getRowCount()):
        solicitante = raw_data.getValueAt(row, 2)  
        descripcion = raw_data.getValueAt(row, 0)  
        numero_peticiones = raw_data.getValueAt(row, 1) 

 
        folder = tree
        for val in [solicitante, descripcion]:
            try:
            
                folder = next(f['items'] for f in folder if f['label'] == val)
            except StopIteration:

                folder.append(
                    {
                        'label': val,
                        'expanded': False,
                        'items': []
                    }
                )
                folder = folder[-1]['items']


        try:
            existing_peticion = next(item for item in folder if "NUMERO PETICIONES" in item['label'])
            existing_peticion['label'] = "NUMERO PETICIONES: {}".format(
                float(existing_peticion['label'].split(": ")[1]) + numero_peticiones
            )
        except StopIteration:
         
            folder.append(
                {
                    'label': "NUMERO PETICIONES: {}".format(numero_peticiones),
                    'expanded': False
                }
            )

    return tree

Why floats ? Do you ever get fractional "peticiones" ? Didn't look like it.

Also, I'll insist: Do it in the query.

1 Like