# Dynamische Filteroptionen

Stellen Sie sich vor, Ihre Filteroptionen aktualisieren sich automatisch basierend auf Ihren tatsächlichen Daten - wie ein intelligenter Assistent, der immer die aktuellsten und relevantesten Auswahlmöglichkeiten bereitstellt, ohne dass Sie manuell Listen pflegen müssen.

## Was sind dynamische Filteroptionen?

Dynamische Filteroptionen verwenden SQL-Abfragen, um Filter automatisch mit Werten aus Ihren Daten zu befüllen, anstatt diese manuell einzugeben:

* **Automatisch aktualisiert** - Filteroptionen spiegeln immer Ihre aktuellen Daten wider
* **SQL-gesteuert** - Schreiben Sie Abfragen, um verfügbare Werte zu ermitteln
* **Anpassung an andere Filter** - Optionen können sich basierend auf anderen Filtern ändern
* **Datengetrieben** - Keine manuellen Listen mehr pflegen
* **Intelligent gefiltert** - Zeigen Sie nur relevante, verfügbare Optionen

**Beispiel aus der Praxis**: Anstatt manuell alle Abteilungsnamen einzugeben, schreibt Ihr Filter eine SQL-Abfrage wie `SELECT DISTINCT abteilung FROM mitarbeiter WHERE aktiv = true LIMIT 10000`, um automatisch alle aktiven Abteilungen als Filteroptionen zu erhalten.

## Dynamisch vs. manuell gesteuerte Filter

{% tabs %}
{% tab title="Dynamische Filter (SQL-gesteuert)" %}
**Filteroptionen werden automatisch aus Daten generiert:**

* **Immer aktuell**: Optionen spiegeln den aktuellen Datenbestand wider
* **Wartungsfrei**: Keine manuellen Updates nötig wenn sich Daten ändern
* **Intelligent**: Können sich basierend auf anderen Filterauswahlen ändern
* **Datengenau**: Zeigen nur Werte, die tatsächlich in den Daten existieren
* **Performant**: Abfragen können optimiert und gecacht werden

**Beste Anwendung für:**

* Abteilungen, die sich häufig ändern
* Status-Listen aus aktuellen Projekten
* Zeiträume basierend auf verfügbaren Daten
* Kategorien, die dynamisch sind
* Abhängige Filteroptionen (Stadt → Postleitzahl)
  {% endtab %}

{% tab title="Manuelle Filter (Eigene Liste)" %}
**Filteroptionen werden manuell eingegeben:**

* **Statisch**: Bleiben gleich bis manuell geändert
* **Wartungsintensiv**: Müssen bei Datenänderungen aktualisiert werden
* **Vorhersagbar**: Optionen ändern sich nicht unerwartet
* **Einfach**: Keine SQL-Kenntnisse erforderlich
* **Kontrolle**: Vollständige Kontrolle über verfügbare Optionen

**Beste Anwendung für:**

* Feste Kategorien (z.B. Prioritätsstufen: Hoch, Mittel, Niedrig)
* Standardisierte Werte
* Einfache, unveränderliche Listen
* Wenn SQL-Abfragen unnötig komplex wären
  {% endtab %}
  {% endtabs %}

## Wie dynamische Filter funktionieren

**Das Grundprinzip:**

1. **SQL-Abfrage schreiben** → Die erste Spalte der Ergebnisse wird zu Ihren Filteroptionen
2. **Automatische Aktualisierung** → Filter führt die Abfrage aus und lädt die aktuellen Werte
3. **Variable Integration** → Andere Filter können als `$variablenname` in der Abfrage verwendet werden
4. **Intelligente Anpassung** → Filteroptionen ändern sich basierend auf anderen Filterauswahlen

**Beispiel-Ablauf:**

* Benutzer wählt "Öffentliche Sicherheit" im Abteilungsfilter
* Status-Filter führt SQL-Abfrage aus: `WHERE abteilung = 'Öffentliche Sicherheit'`
* Status-Optionen zeigen nur relevante Werte für diese Abteilung
* Bei Abteilungsänderung aktualisieren sich die Status-Optionen automatisch

## Dynamische Filter einrichten

{% stepper %}
{% step %}
**Filter erstellen**

1. **Filter erstellen** und **"Auswahlliste"** als Eingabeoption wählen
2. **Im Bereich "Verfügbare Werte"** finden Sie zwei Optionen:
   * **"Eigene Liste"** (manuelle Eingabe)
   * **"Abfrage"** (SQL-gesteuert)
3. **"Abfrage" auswählen** für dynamische Optionen

{% hint style="info" %}
Die "Abfrage"-Option ist nur für Filter mit Auswahllisten verfügbar, nicht für Eingabefelder oder Kalender.
{% endhint %}
{% endstep %}

{% step %}
**SQL-Abfrage schreiben und testen**

1. **"Bearbeiten" klicken** um den SQL-Editor zu öffnen
2. **SQL-Abfrage schreiben**, die Optionen in der ersten Spalte zurückgibt:

```sql
-- Einfaches Beispiel: Alle aktiven Abteilungen
SELECT DISTINCT abteilungsname
FROM abteilungen
WHERE ist_aktiv = true
ORDER BY abteilungsname
LIMIT 10000;
```

3. **"Ausführen" klicken** um die Abfrage zu testen
4. **Ergebnisse in der Vorschau überprüfen**:
   * **Erste Spalte**: Wird zu Ihren Filteroptionen
   * **Zusätzliche Spalten**: Werden ignoriert, können aber zur Orientierung helfen, hier allerdings auf Duplikate achten!
   * **Keine leeren Werte**: NULL oder leere Strings werden automatisch ausgefiltert
5. **"Speichern" klicken** wenn die Abfrage korrekt ist

**Wichtige SQL-Elemente:**

```sql
-- Eindeutige Werte (Duplikate vermeiden), idealerweise nur eine Spalte (z. B. kategorie)
SELECT DISTINCT kategorie

-- Nur relevante Daten
WHERE status = 'aktiv'

-- Sortierung für bessere UX
ORDER BY abteilungsname

-- Maximale Anzahl (immer verwenden)
LIMIT 10000
```

{% endstep %}

{% step %}
**Filter speichern und testen**

1. **Filter speichern** - die SQL-Abfrage wird automatisch mit gespeichert
2. **Filter im Bericht testen**:
   * Filter öffnen → sollte die Werte aus Ihrer SQL-Abfrage zeigen
   * Andere Filter ändern → abhängige Filter sollten sich aktualisieren
   * Daten im System ändern → Filter sollten neue Optionen zeigen

{% hint style="success" %}
Ihr dynamischer Filter ist jetzt aktiv! Die Optionen aktualisieren sich automatisch basierend auf Ihren Daten und anderen Filterauswahlen.
{% endhint %}
{% endstep %}
{% endstepper %}

## Erweiterte Techniken

### Abhängige Filter erstellen

Erstellen Sie Filter, die auf andere Filter reagieren:

```sql
-- Städte basierend auf ausgewähltem Bundesland
SELECT DISTINCT city_name
FROM locations
WHERE state = $bundesland_filter -- <- dies ist der Systemname des Filters "Bundesland"
  AND population > 1000
ORDER BY city_name;
```

**Filter-Verkettung:**

1. **Bundesland-Filter** → Benutzer wählt "Bayern"
2. **Stadt-Filter** → Zeigt nur bayerische Städte
3. **Bezirk-Filter** → Zeigt nur Bezirke der gewählten Stadt

### Optimierung

Für große Datenmengen optimieren Sie Ihre Abfragen:

```sql
-- Indizierte Spalten verwenden
SELECT DISTINCT status
FROM projects
WHERE created_date >= '2024-01-01'  -- Indexed column
  AND department_id IN (1, 2, 3)    -- Indexed values
ORDER BY status
LIMIT 50;

-- Subqueries vermeiden wenn möglich
-- Statt:
SELECT DISTINCT category
FROM products
WHERE id IN (SELECT product_id FROM sales WHERE year = 2024)

-- Besser:
SELECT DISTINCT p.category
FROM products p
JOIN sales s ON p.id = s.product_id
WHERE s.year = 2024;
```

## Praktische Beispiele

### Beispiel 1: Abteilungsfilter mit aktiven Mitarbeitern

```sql
-- Zeigt nur Abteilungen, die derzeit aktive Mitarbeiter haben
SELECT DISTINCT a.abteilungsname
FROM abteilungen a
JOIN mitarbeiter m ON a.id = m.abteilungs_id
WHERE m.status = 'aktiv'
  AND m.ende_datum IS NULL
ORDER BY a.abteilungsname
LIMIT 10000;
```

### Beispiel 2: Statusfilter basierend auf Projekt und Jahr

```sql
-- Zeigt nur Status, die für das gewählte Projekt und Jahr existieren
SELECT DISTINCT projektstatus
FROM projekt_historie
WHERE projekt_typ = $projekt_typ
  AND YEAR(erstellt_datum) = $jahr
  AND projektstatus IS NOT NULL
ORDER BY 
  CASE projektstatus
    WHEN 'Geplant' THEN 1
    WHEN 'In Bearbeitung' THEN 2
    WHEN 'Abgeschlossen' THEN 3
    ELSE 4
  END
LIMIT 10000;
```

## Fehlerbehebung

### "Keine Optionen verfügbar"

**Mögliche Ursachen:**

* SQL-Abfrage gibt keine Ergebnisse zurück
* Erste Spalte enthält nur NULL-Werte

**Lösungsansätze:**

```sql
-- Debug-Version: Zeigt auch NULL-Werte
SELECT DISTINCT 
  abteilungsname,
  COUNT(*) as anzahl_datensaetze
FROM projekte
GROUP BY abteilungsname
ORDER BY abteilungsname
LIMIT 10000;

-- Explizit NULL-Werte ausschließen
SELECT DISTINCT abteilungsname
FROM projekte
WHERE abteilungsname IS NOT NULL
  AND abteilungsname != ''
  AND TRIM(abteilungsname) != ''
LIMIT 10000;
```

### "Filter aktualisiert sich nicht"

**Häufige Probleme:**

* Variablennamen stimmen nicht mit anderen Filtern überein
* SQL-Syntax-Fehler verhindert Ausführung
* Speicher-Probleme bei sehr häufigen Änderungen

**Diagnose:**

1. **SQL-Editor öffnen** → "Ausführen" klicken → Fehlermeldungen prüfen
2. **Variable Namen überprüfen** → Müssen exakt mit Filter-Systemnamen übereinstimmen
3. **Browser-Cache leeren** → Manchmal hilft ein Neuladen der Seite

### "Leistungs-Probleme"

**Für langsame Abfragen:**

```sql
-- LIMIT ist Pflicht (maximal 10.000 Zeilen)
SELECT DISTINCT kategorie
FROM grosse_tabelle
WHERE bedingungen
ORDER BY kategorie
LIMIT 10000;

-- Indizierte Spalten in WHERE nutzen
WHERE indizierte_spalte = wert
```

{% hint style="warning" %}
**Wichtig**: Dynamische Filter führen SQL-Abfragen bei jeder Verwendung aus. Achten Sie auf die Leistung bei großen Datenmengen und häufig genutzten Filtern.
{% endhint %}

## Best Practices

### SQL-Abfragen schreiben

1. **Erste Spalte ist entscheidend** - Nur die erste Spalte wird für Optionen verwendet
2. **DISTINCT verwenden** - Vermeidet doppelte Einträge in der Dropdown-Liste
3. **ORDER BY hinzufügen** - Sortiert Optionen für bessere Benutzererfahrung
4. **NULL-Werte filtern** - Leere Optionen vermeiden
5. **Leistung beachten** - Immer LIMIT 10000 verwenden (Pflicht)

### Variablen verwenden

1. **Exakte Namen verwenden** - `$filter_systemname` muss genau mit dem Filter-Systemnamen (Slug) übereinstimmen
2. **NULL-Behandlung** - Berücksichtigen Sie leere Filter: `WHERE (status = $status OR $status IS NULL)`
3. **Typen beachten** - Text-, Zahlen- und Datumsfilter haben verschiedene Formate

### Wartung und Überwachung

1. **Regelmäßig testen** - Überprüfen Sie Filter nach Datenbank-Änderungen
2. **Leistung überwachen** - Langsame Abfragen können die Benutzererfahrung beeinträchtigen (maximal 10.000 Zeilen möglich)
3. **Dokumentation** - Kommentieren Sie komplexe SQL-Abfragen für andere Bearbeiter

{% hint style="success" %}
**Profi-Tipp**: Beginnen Sie mit einfachen DISTINCT-Abfragen und erweitern Sie diese schrittweise um Variablen und Logik. Testen Sie jede Änderung sofort im SQL-Editor, bevor Sie den Filter speichern.
{% endhint %}
