diff --git a/dashboards/dashboard_base.py b/dashboards/dashboard_base.py
index d6dfa481871e7d258219f46ef1ddfe0461cb6cae..ccbc81c197a6a187a144a2b5f15ea9549c215fe7 100644
--- a/dashboards/dashboard_base.py
+++ b/dashboards/dashboard_base.py
@@ -14,10 +14,11 @@ from dashboards.annotations import Annotation
 from dashboards.influx_queries import Query
 
 
-def get_influx_target(target_query: str, result_format: str = 'time_series', **kwargs) -> InfluxDBTarget:
+def get_influx_target(target_query: str, result_format: str = 'time_series', alias: str = "", **kwargs) -> InfluxDBTarget:
     return InfluxDBTarget(
         query=target_query,
         format=result_format,
+        alias=alias,
         **{k: v for k, v in kwargs.items() if v is not None},
     )
 
diff --git a/dashboards/dashboard_walberla.py b/dashboards/dashboard_walberla.py
index 501f453887a6a3ba685ebdbce3c5e021847ba558..78410e304b84aa44fb2ee2f64c43e13f168ba795 100644
--- a/dashboards/dashboard_walberla.py
+++ b/dashboards/dashboard_walberla.py
@@ -18,7 +18,7 @@ from dashboards.dashboard_base import (
     get_grid_pos,
     pack_in_row,
 )
-from dashboards.influx_queries import join_variable_and, get_variable_condition_with_tag
+from dashboards.influx_queries import join_variable_and, get_variable_condition_with_tag, get_variable_tag, join_conditions, get_variable_condition, get_variable_condition_without_regex
 from dashboards.legends import Units
 from dashboards.overrides import get_color_regex_override
 from dashboards.panels import PanelInfos, get_time_series_panel, get_table_panel, get_bar_chart_panel
@@ -28,6 +28,11 @@ from dashboards.variables import (
     get_time_dependend_dashboard_variable,
     get_field_keys_dashboard_variable,
 )
+from dashboards.influx_queries import Query
+
+
+def is_regex(name):
+    return name[0] == "/" and name[-1] == "/"
 
 
 def dashboard_uniformgridcpu():
@@ -307,10 +312,57 @@ def dashboard_uniformgridcpu_relativeperformance():
         Filter("BandwidthBenchmark", multi=True, default_value="bw_stream"),
     ]
 
+    fieldConfig = {
+    "defaults": {
+      "custom": {
+        "lineWidth": 1,
+        "fillOpacity": 80,
+        "gradientMode": "none",
+        "axisPlacement": "auto",
+        "axisLabel": "",
+        "axisColorMode": "text",
+        "axisBorderShow": False,
+        "scaleDistribution": {
+          "type": "linear"
+        },
+        "axisCenteredZero": False,
+        "hideFrom": {
+          "tooltip": False,
+          "viz": False,
+          "legend": False
+        },
+        "thresholdsStyle": {
+          "mode": "off"
+        }
+      },
+      "color": {
+        "mode": "palette-classic"
+      },
+      "mappings": [],
+      "thresholds": {
+        "mode": "absolute",
+        "steps": [
+          {
+            "color": "green",
+            "value": None
+          },
+          {
+            "color": "red",
+            "value": 80
+          }
+        ]
+      },
+      "fieldMinMax": True,
+      "max": 1,
+      "unit": "percentunit"
+    },
+    "overrides": []
+  }
+
     fields = [
         PanelInfos("Relative Performance", Units.number, absthreshold=80),
         PanelInfos("Bandwidth", Units.number, absthreshold=80),
-        PanelInfos("Relative Performance", Units.mbytes_per_second, absthreshold=80),
+        PanelInfos("Relative Performance", Units.percent, absthreshold=80),
     ]
 
     filter_vars = [
@@ -326,57 +378,252 @@ def dashboard_uniformgridcpu_relativeperformance():
 
     row_repeat_var = [fv for fv in filter_vars if fv.name == row_repeat][0]
 
-    where = [
-        join_variable_and([f.name for f in filters]),
-        get_variable_condition_with_tag(filters[0].name),
-        join_variable_and([f.name for f in filters])
-    ]
+    where0A2 = join_conditions(
+        [
+            get_variable_condition_with_tag(filters[i].name) for i in range(2)
+        ] + [
+            get_variable_condition_without_regex(filters[i].name) for i in [2]
+        ] + [
+            get_variable_condition(filters[3].name)
+        ] + [
+            get_variable_condition_without_regex(filters[i].name) for i in [4]
+        ], "AND"
+    )
+    where0B2 = get_variable_condition_with_tag(filters[0].name)
+    where1A = get_variable_condition_with_tag(filters[0].name)
+    where2A2 = join_conditions(
+        [
+            get_variable_condition_with_tag(filters[i].name) for i in range(2)
+        ] + [
+            get_variable_condition_without_regex(filters[i].name) for i in [2]
+        ] + [
+            get_variable_condition(filters[3].name)
+        ] + [
+            get_variable_condition_without_regex(filters[i].name) for i in [4]
+        ], "AND"
+    )
+    where2B2 = get_variable_condition_with_tag(filters[0].name)
+
+    group_by0A2 = ["host", "project_id", "branch", "collisionSetup", "mpi_num_processes", "streamingPattern", "timeStepStrategy", "stencil", "blocks_0", "blocks_1", "blocks_2", "cellsPerBlock_0", "cellsPerBlock_1", "cellsPerBlock_2", "periodic_0", "periodic_1", "periodic_2"]
+    group_by0B2 = [get_variable_tag(filters[0].name)]
+    group_by1A = [filters[0].name]
+    group_by2A2 = ["host", "project_id", "branch", "collisionSetup", "mpi_num_processes", "streamingPattern", "timeStepStrategy", "stencil", "blocks_0", "blocks_1", "blocks_2", "cellsPerBlock_0", "cellsPerBlock_1", "cellsPerBlock_2", "periodic_0", "periodic_1", "periodic_2"]
+    group_by2B2 = [get_variable_tag(filters[0].name)]
+    
     annotations = get_commit_annotation(
         data_source, "red", "commits", measurment_name2)
 
-    selected_columns = [
-        ", ".join([
-        "host",
-        "collisionSetup",
-        "MLUPSperProcess",
-        "mpi_num_processes"]),
-        ", ".join([
+    selected_columns0A1 = ", ".join([
+        '"host"',
+        '"collisionSetup"',
+        '"MLUPSperProcess"',
+        '"mpi_num_processes"'])
+    selected_columns0A2 = ", ".join([
+        '(last("mlupsPerProcess")) as "MLUPSperProcess"',
+        '"mpi_num_processes"'])
+    selected_columns0B1 = ", ".join([
+        '"host"',
+        '"P_max"'])
+    selected_columns0B2 = ", ".join([
+        'last($BandwidthBenchmark)/(27*2*8) as "P_max"'])
+    selected_columns1A = ", ".join([
         'last($BandwidthBenchmark) as "BW[MByte/s]"',
-        'last($BandwidthBenchmark) / (27 * 2 * 8) as "P_max[MLUPS]"']),
-        ", ".join([
-        "host",
-        "collisionSetup",
-        "MLUPSperProcess",
-        "mpi_num_processes"]),
-    ]
+        'last($BandwidthBenchmark)/(27*2*8) as "P_max[MLUPS]"'])
+    selected_columns2A1 = ", ".join([
+        '"host"',
+        '"collisionSetup"',
+        '"MLUPSperProcess"',
+        '"mpi_num_processes"'])
+    selected_columns2A2 = ", ".join([
+        '(last("mlupsPerProcess")) as "MLUPSperProcess"',
+        '"mpi_num_processes"'])
+    selected_columns2B1 = ", ".join([
+        '"host"',
+        '"P_max"'])
+    selected_columns2B2 = ", ".join([
+        'last($BandwidthBenchmark)/(27*2*8) as "P_max"'])
+
+
+    query0A2 = Query(select_=selected_columns0A2,
+                  from_=measurment_name,
+                  where_=where0A2,
+                  group_by=group_by0A2,
+                  from_string=not is_regex(measurment_name),
+                  select_string=False)
+    query0A1 = Query(selected_columns0A1,
+                  from_=query0A2,
+                  from_string=not is_regex(measurment_name),
+                  select_string=False)
+    query0B2 = Query(select_=selected_columns0B2,
+                  from_=measurment_name2,
+                  where_=where0B2,
+                  group_by=group_by0B2,
+                  from_string=not is_regex(measurment_name),
+                  select_string=False)   
+    query0B1 = Query(select_=selected_columns0B1,
+                  from_=query0B2,
+                  from_string=not is_regex(measurment_name),
+                  select_string=False)     
+
+    query1A = Query(select_=selected_columns1A,
+                  from_=measurment_name2,
+                  where_=where1A,
+                  group_by=group_by1A,
+                  from_string=not is_regex(measurment_name),
+                  select_string=False)
+
+    query2A2 = Query(select_=selected_columns2A2,
+                  from_=measurment_name,
+                  where_=where2A2,
+                  group_by=group_by2A2,
+                  from_string=not is_regex(measurment_name),
+                  select_string=False)
+    query2A1 = Query(selected_columns2A1,
+                  from_=query2A2,
+                  from_string=not is_regex(measurment_name),
+                  select_string=False)
+    query2B2 = Query(select_=selected_columns2B2,
+                  from_=measurment_name2,
+                  where_=where2B2,
+                  group_by=group_by2B2,
+                  from_string=not is_regex(measurment_name),
+                  select_string=False)   
+    query2B1 = Query(select_=selected_columns2B1,
+                  from_=query2B2,
+                  from_string=not is_regex(measurment_name),
+                  select_string=False)  
+
+    alias0A = "$tag_collisionSetup"
+    alias2A = "$tag_collisionSetup"
+                  
+
+    transformations0 = [
+    {
+      "id": "joinByField",
+      "options": {
+        "byField": "host",
+        "mode": "outerTabular"
+      }
+    },
+    {
+      "id": "calculateField",
+      "options": {
+        "alias": "P",
+        "binary": {
+          "left": "MLUPSperProcess",
+          "operator": "*",
+          "right": "mpi_num_processes"
+        },
+        "mode": "binary",
+        "reduce": {
+          "reducer": "sum"
+        },
+        "replaceFields": False
+      }
+    },
+    {
+      "id": "calculateField",
+      "options": {
+        "binary": {
+          "left": "P",
+          "operator": "/",
+          "right": "P_max"
+        },
+        "mode": "binary",
+        "reduce": {
+          "reducer": "sum"
+        }
+      }
+    },
+    {
+      "id": "filterFieldsByName",
+      "options": {
+        "include": {
+          "names": [
+            "Time 1",
+            "collisionSetup",
+            "P",
+            "P / P_max",
+            "MLUPSperProcess"
+          ]
+        }
+      }
+    }
+  ]
+
+    transformations2 = [
+    {
+      "id": "joinByField",
+      "options": {
+        "byField": "host",
+        "mode": "outerTabular"
+      }
+    },
+    {
+      "id": "calculateField",
+      "options": {
+        "alias": "P",
+        "binary": {
+          "left": "MLUPSperProcess",
+          "operator": "*",
+          "right": "mpi_num_processes"
+        },
+        "mode": "binary",
+        "reduce": {
+          "reducer": "sum"
+        },
+        "replaceFields": False
+      }
+    },
+    {
+      "id": "calculateField",
+      "options": {
+        "binary": {
+          "left": "P",
+          "operator": "/",
+          "right": "P_max"
+        },
+        "mode": "binary",
+        "reduce": {
+          "reducer": "sum"
+        }
+      }
+    },
+    {
+      "id": "filterFieldsByName",
+      "options": {
+        "include": {
+          "names": [
+            "collisionSetup",
+            "P / P_max"
+          ]
+        }
+      }
+    }
+  ]
 
     panels = [
         # Panel 0
         get_table_panel(
             fields[0],
-            selected_columns[0],
             data_source,
-            measurment_name,
-            where=where[0],
-            group_by=[f.name for f in filters],
+            [query0A1, query0B1],
+            alias_list = [alias0A, ""],
+            transformations=transformations0,
         ),
         # Panel 1
         get_table_panel(
             fields[1],
-            selected_columns[1],
             data_source,
-            measurment_name2,
-            where=where[1],
-            group_by=[filters[0].name],
+            [query1A],
         ),
         # Panel 2
         get_bar_chart_panel(
             fields[2],
-            selected_columns[2],
             data_source,
-            measurment_name,
-            where=where[2],
-            group_by=[f.name for f in filters],
+            [query2A1, query2B1],
+            alias_list = [alias2A, ""],
+            transformations=transformations2,
         ),
     ]
 
diff --git a/dashboards/influx_queries.py b/dashboards/influx_queries.py
index 7bd23de2fb11aad7acc1460de54204a98b777326..cc7045ae35b925094a85c1875fcfafa4aa6aeb9d 100644
--- a/dashboards/influx_queries.py
+++ b/dashboards/influx_queries.py
@@ -6,8 +6,8 @@ from typing import List, Union
 @dataclass
 class Query:
     select_: str
-    from_: str
-    where_: str
+    from_: Union[str, 'Query']
+    where_: str = None
     group_by: List[str] = field(default_factory=list)
     select_string: bool = True
     from_string: bool = True
@@ -19,17 +19,22 @@ class Query:
             return f"SELECT {self.select_} "
 
     def _get_from(self):
-        if self.from_string:
+        if isinstance(self.from_, Query):
+            return f'FROM ({self.from_}) '
+        elif self.from_string:
             return f'FROM "{self.from_}" '
         else:
             return f"FROM {self.from_} "
 
     def _get_where(self):
-        return f"WHERE ({self.where_}) "
+        if self.where_:
+            return f"WHERE ({self.where_}) "
+        else:
+            return ""
 
     def _get_group_by(self):
         if self.group_by:
-            group_by = ", ".join(f'"{tag}"' for tag in self.group_by)
+            group_by = ", ".join(tag if tag.endswith("::tag") else f'"{tag}"' for tag in self.group_by)
             return f"GROUP BY {group_by}"
         else:
             return ""
@@ -80,6 +85,7 @@ def get_variable_condition(variable_name: str, *, tag_key: str = None) -> str:
         raise ValueError("Empty variable name")
     return f'"{clean_lhs}" =~ /^${{{clean_rhs}:regex}}$/'
 
+
 def get_variable_condition_with_tag(variable_name: str, *, tag_key: str = None) -> str:
     clean_rhs = variable_name.strip()
     if tag_key:
@@ -91,6 +97,28 @@ def get_variable_condition_with_tag(variable_name: str, *, tag_key: str = None)
     return f'"{clean_lhs}"::tag =~ /^${clean_rhs}$/'
 
 
+def get_variable_condition_without_regex(variable_name: str, *, tag_key: str = None) -> str:
+    clean_rhs = variable_name.strip()
+    if tag_key:
+        clean_lhs = tag_key.strip()
+    else:
+        clean_lhs = clean_rhs
+    if not clean_rhs:
+        raise ValueError("Empty variable name")
+    return f'"{clean_lhs}" =~ /^${clean_rhs}$/'
+
+
+def get_variable_tag(variable_name: str, *, tag_key: str = None) -> str:
+    clean_rhs = variable_name.strip()
+    if tag_key:
+        clean_lhs = tag_key.strip()
+    else:
+        clean_lhs = clean_rhs
+    if not clean_rhs:
+        raise ValueError("Empty variable name")
+    return f'"{clean_lhs}"::tag'
+
+
 def join_conditions(conditions: List[str], operators: Union[List[str], str], include_time_filter: bool = True):
     ops = operators
     if isinstance(operators, str):
diff --git a/dashboards/panels.py b/dashboards/panels.py
index 1b153e073f39c882294950ecee62b8936c79670a..bfe23ccb2b86cc82c89ffbd1ce874793fb0dfe2c 100644
--- a/dashboards/panels.py
+++ b/dashboards/panels.py
@@ -96,20 +96,19 @@ def get_stat_panel(title: str,
 
 
 def get_table_panel(panel_infos: PanelInfos,
-                          selected_columns: str,
                           data_source: str,
-                          measurment_name: str,
+                          query_list: list[Query],
                           *,
-                          where=None,
-                          group_by=None,
+                          result_format_list: list[str] = None,
+                          alias_list: list[str] = None,
+                          transformations=[],
                           overrides=None,
                           **kwargs):
-    query = Query(select_=selected_columns,
-                  from_=measurment_name,
-                  where_=where,
-                  group_by=group_by,
-                  from_string=not is_regex(measurment_name),
-                  select_string=False)
+    if not alias_list:
+        alias_list = [''] * len(query_list)
+    if not result_format_list:
+        result_format_list = ['table'] * len(query_list)
+    targets = [get_influx_target(str(query), result_format=result_format, alias=alias) for query, result_format, alias in zip(query_list, result_format_list, alias_list)]
     new_kwargs = {**kwargs}
     if panel_infos.absthreshold is not None:
         new_kwargs.update({'thresholdType': 'absolute',
@@ -117,12 +116,12 @@ def get_table_panel(panel_infos: PanelInfos,
                                           Threshold('red', index=1, value=float(panel_infos.absthreshold), op='lt'), ],
                            }
                           )
-    result_format = ['table']
 
     return Table(
         title=panel_infos.name,
         dataSource=data_source,
-        targets=[get_influx_target(str(query), result_format[0])],
+        targets=targets,
+        transformations=transformations,
         unit=panel_infos.unit,
         overrides=overrides,
         **new_kwargs,
@@ -131,20 +130,19 @@ def get_table_panel(panel_infos: PanelInfos,
 
 
 def get_bar_chart_panel(panel_infos: PanelInfos,
-                          selected_columns: str,
                           data_source: str,
-                          measurment_name: str,
+                          query_list: list[Query],
                           *,
-                          where=None,
-                          group_by=None,
+                          result_format_list: list[str] = None,
+                          alias_list: list[str] = None,
+                          transformations=[],
                           overrides=None,
                           **kwargs):
-    query = Query(select_=selected_columns,
-                  from_=measurment_name,
-                  where_=where,
-                  group_by=group_by,
-                  from_string=not is_regex(measurment_name),
-                  select_string=False)
+    if not alias_list:
+        alias_list = [''] * len(query_list)
+    if not result_format_list:
+        result_format_list = ['table'] * len(query_list)
+    targets = [get_influx_target(str(query), result_format=result_format, alias=alias) for query, result_format, alias in zip(query_list, result_format_list, alias_list)]
     new_kwargs = {**kwargs}
     if panel_infos.absthreshold is not None:
         new_kwargs.update({'thresholdType': 'absolute',
@@ -152,12 +150,14 @@ def get_bar_chart_panel(panel_infos: PanelInfos,
                                           Threshold('red', index=1, value=float(panel_infos.absthreshold), op='lt'), ],
                            }
                           )
-    result_format = ['table']
+
 
     return BarChart(
         title=panel_infos.name,
         dataSource=data_source,
-        targets=[get_influx_target(str(query), result_format[0])],
+        targets=targets,
+        transformations=transformations,
+        xTickLabelRotation=-45,
         **new_kwargs,
 
     )