Fügt Unterstützung für parallele Entwicklungsumgebungen hinzu und aktualisiert die Benutzeroberfläche. Neue Routen und Komponenten für Trainingsstatistiken implementiert. Fehlerbehebungen und Verbesserungen in der Benutzeroberfläche vorgenommen.
This commit is contained in:
139
backend/README_CLEANUP.md
Normal file
139
backend/README_CLEANUP.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# MySQL Keys Cleanup - Anleitung
|
||||
|
||||
## Problem
|
||||
Der MySQL-Server hat ein Limit von maximal 64 Keys pro Tabelle. Sequelize erstellt automatisch viele INDEX für verschiedene Felder, was dieses Limit überschreitet.
|
||||
|
||||
## Wichtige Erkenntnis ⚠️
|
||||
**Alle INDEX-Namen in den ursprünglichen Scripts existieren nicht!** Das bedeutet, dass die Tabellennamen oder INDEX-Namen nicht mit der Realität übereinstimmen.
|
||||
|
||||
## Lösung
|
||||
Das Cleanup-Script entfernt überflüssige INDEX, behält aber die essentiellen Keys (PRIMARY KEY, UNIQUE Keys).
|
||||
|
||||
## Verfügbare Scripts (nach Priorität sortiert)
|
||||
|
||||
### **1. `checkRealIndexes.sql`** - Echte INDEX überprüfen ⭐ EMPFOHLEN ZUERST
|
||||
- Zeigt alle vorhandenen Tabellen in der Datenbank an
|
||||
- Zeigt alle **echten** INDEX und Keys an
|
||||
- Zeigt die Anzahl der Keys pro Tabelle an
|
||||
- **Verwenden Sie dieses Script zuerst, um die echten INDEX-Namen zu sehen!**
|
||||
|
||||
### **2. `cleanupKeysMinimal.sql`** - Minimales Cleanup ⭐ EMPFOHLEN
|
||||
- Zeigt alle INDEX pro Tabelle mit `SHOW INDEX`
|
||||
- Entfernt alle überflüssigen INDEX
|
||||
- Behält nur PRIMARY KEY und UNIQUE Keys
|
||||
- **Sicherste Option für die Bereinigung**
|
||||
|
||||
### **3. `cleanupKeysReal.sql`** - Cleanup mit echten Namen
|
||||
- Zeigt alle vorhandenen INDEX vor und nach der Bereinigung
|
||||
- Entfernt nur INDEX, die tatsächlich existieren
|
||||
- Detaillierte Informationen über den Cleanup-Prozess
|
||||
|
||||
### **4. `checkTableNames.sql`** - Tabellennamen überprüfen
|
||||
- Zeigt alle vorhandenen Tabellen und INDEX an
|
||||
- Gute Übersicht über die Datenbankstruktur
|
||||
|
||||
### **5. `cleanupKeysSmart.sql`** - Intelligentes Cleanup (veraltet)
|
||||
- Überprüft zuerst alle vorhandenen Tabellen und INDEX
|
||||
- **Problem**: Verwendet falsche INDEX-Namen
|
||||
|
||||
### **6. `cleanupKeysCorrected.sql`** - Korrigierte Tabellennamen (veraltet)
|
||||
- Verwendet die wahrscheinlich korrekten Tabellennamen
|
||||
- **Problem**: Verwendet falsche INDEX-Namen
|
||||
|
||||
### **7. `cleanupKeys.sql` & `cleanupKeysSimple.sql`** (veraltet)
|
||||
- Tabellennamen und INDEX-Namen könnten falsch sein
|
||||
- **Nicht mehr empfohlen**
|
||||
|
||||
## Empfohlener Ablauf
|
||||
|
||||
### **Schritt 1: Echte INDEX überprüfen**
|
||||
```bash
|
||||
# Verbindung zur MySQL-Datenbank
|
||||
mysql -u [username] -p [database_name]
|
||||
|
||||
# Script ausführen
|
||||
source /path/to/checkRealIndexes.sql
|
||||
```
|
||||
|
||||
### **Schritt 2: Minimales Cleanup durchführen**
|
||||
```bash
|
||||
# Script ausführen
|
||||
source /path/to/cleanupKeysMinimal.sql
|
||||
```
|
||||
|
||||
### **Alternative Ausführungsmethoden**
|
||||
|
||||
#### Über MySQL Workbench
|
||||
1. MySQL Workbench öffnen
|
||||
2. Verbindung zur Datenbank herstellen
|
||||
3. File -> Open SQL Script -> Script auswählen
|
||||
4. Execute (Blitz-Symbol) klicken
|
||||
|
||||
#### Über phpMyAdmin
|
||||
1. phpMyAdmin öffnen
|
||||
2. Datenbank `trainingsdiary` auswählen
|
||||
3. SQL-Tab öffnen
|
||||
4. Inhalt des Scripts einfügen
|
||||
5. Go klicken
|
||||
|
||||
## Nach der Ausführung
|
||||
|
||||
1. **Keys überprüfen:**
|
||||
```sql
|
||||
SELECT COUNT(*) as total_keys
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
```
|
||||
|
||||
2. **Keys pro Tabelle anzeigen:**
|
||||
```sql
|
||||
SELECT TABLE_NAME, COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
```
|
||||
|
||||
3. **Server neu starten:**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Wichtige Hinweise
|
||||
|
||||
- **Backup erstellen:** Vor der Ausführung ein Backup der Datenbank erstellen
|
||||
- **Nur essentiellste Keys:** Das Script behält PRIMARY KEY und UNIQUE Keys bei
|
||||
- **Performance:** Weniger Keys können die Abfrage-Performance beeinflussen
|
||||
- **Sequelize:** Nach dem Cleanup kann Sequelize die Keys bei Bedarf neu erstellen
|
||||
|
||||
## Empfohlener Ablauf
|
||||
|
||||
1. **`checkRealIndexes.sql` ausführen** - Echte INDEX-Namen sehen
|
||||
2. **`cleanupKeysMinimal.sql` ausführen** - Minimales Cleanup
|
||||
3. **Ergebnisse überprüfen** - Keys zählen
|
||||
4. **Server neu starten** - `npm run dev`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Fehler: "Can't DROP INDEX; check that it exists"
|
||||
- **Das ist normal!** Alle INDEX-Namen in den ursprünglichen Scripts existieren nicht
|
||||
- Verwenden Sie `checkRealIndexes.sql` um die echten INDEX-Namen zu sehen
|
||||
- Verwenden Sie `cleanupKeysMinimal.sql` für das Cleanup
|
||||
|
||||
### Fehler: "Table doesn't exist"
|
||||
- Verwenden Sie `checkRealIndexes.sql` um die echten Tabellennamen zu sehen
|
||||
- Passen Sie die Scripts entsprechend an
|
||||
|
||||
### Fehler: "Index doesn't exist"
|
||||
- Das ist normal - `DROP INDEX IF EXISTS` verhindert Fehler
|
||||
- Nicht vorhandene INDEX werden einfach übersprungen
|
||||
|
||||
### Keys werden immer noch erstellt
|
||||
- Sequelize erstellt Keys automatisch bei `sync()`
|
||||
- Das ist normal und gewünscht
|
||||
- Nur überflüssige Keys werden entfernt
|
||||
|
||||
### MySQL-Key-Limit überschritten
|
||||
- Führen Sie das minimale Cleanup-Script aus
|
||||
- Überprüfen Sie die Anzahl der Keys nach der Bereinigung
|
||||
- Falls nötig, entfernen Sie weitere INDEX manuell basierend auf den echten Namen
|
||||
46
backend/checkRealIndexes.sql
Normal file
46
backend/checkRealIndexes.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- Script zum Überprüfen der echten INDEX-Namen
|
||||
USE trainingsdiary;
|
||||
|
||||
-- Alle vorhandenen Tabellen anzeigen
|
||||
SELECT '=== VORHANDENE TABELLEN ===' as info;
|
||||
SHOW TABLES;
|
||||
|
||||
-- Alle vorhandenen INDEX und Keys anzeigen (mit echten Namen)
|
||||
SELECT '=== ALLE INDEX UND KEYS ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
INDEX_NAME,
|
||||
COLUMN_NAME,
|
||||
NON_UNIQUE,
|
||||
SEQ_IN_INDEX
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;
|
||||
|
||||
-- Anzahl der Keys pro Tabelle
|
||||
SELECT '=== KEYS PRO TABELLE ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- Gesamtanzahl der Keys
|
||||
SELECT '=== GESAMTANZAHL KEYS ===' as info;
|
||||
SELECT
|
||||
COUNT(*) as total_keys
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
|
||||
-- Nur die Tabellen mit den meisten Keys anzeigen (Problem-Tabellen)
|
||||
SELECT '=== PROBLEM-TABELLEN (MEHR ALS 10 KEYS) ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
HAVING COUNT(*) > 10
|
||||
ORDER BY key_count DESC;
|
||||
35
backend/checkTableNames.sql
Normal file
35
backend/checkTableNames.sql
Normal file
@@ -0,0 +1,35 @@
|
||||
-- Script zum Überprüfen der echten Tabellennamen
|
||||
USE trainingsdiary;
|
||||
|
||||
-- Alle Tabellen in der Datenbank anzeigen
|
||||
SHOW TABLES;
|
||||
|
||||
-- Detaillierte Informationen über alle Tabellen
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
TABLE_ROWS,
|
||||
DATA_LENGTH,
|
||||
INDEX_LENGTH
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
ORDER BY TABLE_NAME;
|
||||
|
||||
-- Alle INDEX und Keys pro Tabelle anzeigen
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
INDEX_NAME,
|
||||
COLUMN_NAME,
|
||||
NON_UNIQUE,
|
||||
SEQ_IN_INDEX
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;
|
||||
|
||||
-- Anzahl der Keys pro Tabelle
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
185
backend/cleanupKeys.sql
Normal file
185
backend/cleanupKeys.sql
Normal file
@@ -0,0 +1,185 @@
|
||||
-- Cleanup-Script für MySQL Keys
|
||||
-- Führt dieses Script in der MySQL-Datenbank aus, um überflüssige Keys zu entfernen
|
||||
|
||||
USE trainingsdiary;
|
||||
|
||||
-- 1. Alle nicht-essentiellen Keys aus der member-Tabelle entfernen
|
||||
-- (behält nur PRIMARY KEY und UNIQUE Keys für kritische Felder)
|
||||
|
||||
-- Überflüssige INDEX entfernen (falls vorhanden)
|
||||
DROP INDEX IF EXISTS idx_member_hashed_id ON member;
|
||||
DROP INDEX IF EXISTS idx_member_first_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_last_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_birth_date ON member;
|
||||
DROP INDEX IF EXISTS idx_member_active ON member;
|
||||
DROP INDEX IF EXISTS idx_member_created_at ON member;
|
||||
DROP INDEX IF EXISTS idx_member_updated_at ON member;
|
||||
|
||||
-- 2. Überflüssige Keys aus anderen Tabellen entfernen
|
||||
-- User-Tabelle
|
||||
DROP INDEX IF EXISTS idx_user_email ON user;
|
||||
DROP INDEX IF EXISTS idx_user_created_at ON user;
|
||||
DROP INDEX IF EXISTS idx_user_updated_at ON user;
|
||||
|
||||
-- Clubs-Tabelle
|
||||
DROP INDEX IF EXISTS idx_clubs_name ON clubs;
|
||||
DROP INDEX IF EXISTS idx_clubs_created_at ON clubs;
|
||||
DROP INDEX IF EXISTS idx_clubs_updated_at ON clubs;
|
||||
|
||||
-- User_Club-Tabelle
|
||||
DROP INDEX IF EXISTS idx_user_club_approved ON user_club;
|
||||
DROP INDEX IF EXISTS idx_user_club_created_at ON user_club;
|
||||
DROP INDEX IF EXISTS idx_user_club_updated_at ON user_club;
|
||||
|
||||
-- Log-Tabelle
|
||||
DROP INDEX IF EXISTS idx_log_activity ON log;
|
||||
DROP INDEX IF EXISTS idx_log_created_at ON log;
|
||||
DROP INDEX IF EXISTS idx_log_updated_at ON log;
|
||||
|
||||
-- Diary_Dates-Tabelle
|
||||
DROP INDEX IF EXISTS idx_diary_dates_date ON diary_dates;
|
||||
DROP INDEX IF EXISTS idx_diary_dates_created_at ON diary_dates;
|
||||
DROP INDEX IF EXISTS idx_diary_dates_updated_at ON diary_dates;
|
||||
|
||||
-- Participants-Tabelle
|
||||
DROP INDEX IF EXISTS idx_participant_created_at ON participants;
|
||||
DROP INDEX IF EXISTS idx_participant_updated_at ON participants;
|
||||
|
||||
-- Activity-Tabelle
|
||||
DROP INDEX IF EXISTS idx_activity_created_at ON activities;
|
||||
DROP INDEX IF EXISTS idx_activity_updated_at ON activities;
|
||||
|
||||
-- Member_Note-Tabelle
|
||||
DROP INDEX IF EXISTS idx_member_note_created_at ON member_note;
|
||||
DROP INDEX IF EXISTS idx_member_note_updated_at ON member_note;
|
||||
|
||||
-- Diary_Note-Tabelle
|
||||
DROP INDEX IF EXISTS idx_diary_note_created_at ON diary_note;
|
||||
DROP INDEX IF EXISTS idx_diary_note_updated_at ON diary_note;
|
||||
|
||||
-- Diary_Tag-Tabelle
|
||||
DROP INDEX IF EXISTS idx_diary_tag_created_at ON diary_tag;
|
||||
DROP INDEX IF EXISTS idx_diary_tag_updated_at ON diary_tag;
|
||||
|
||||
-- Member_Diary_Tag-Tabelle
|
||||
DROP INDEX IF EXISTS idx_member_diary_tag_created_at ON member_diary_tag;
|
||||
DROP INDEX IF EXISTS idx_member_diary_tag_updated_at ON member_diary_tag;
|
||||
|
||||
-- Diary_Date_Tag-Tabelle
|
||||
DROP INDEX IF EXISTS idx_diary_date_tag_created_at ON diary_date_tag;
|
||||
DROP INDEX IF EXISTS idx_diary_date_tag_updated_at ON diary_date_tag;
|
||||
|
||||
-- Diary_Member_Note-Tabelle
|
||||
DROP INDEX IF EXISTS idx_diary_member_note_created_at ON diary_member_note;
|
||||
DROP INDEX IF EXISTS idx_diary_member_note_updated_at ON diary_member_note;
|
||||
|
||||
-- Predefined_Activity-Tabelle
|
||||
DROP INDEX IF EXISTS idx_predefined_activity_created_at ON predefined_activities;
|
||||
DROP INDEX IF EXISTS idx_predefined_activity_updated_at ON predefined_activities;
|
||||
|
||||
-- Diary_Date_Activity-Tabelle
|
||||
DROP INDEX IF EXISTS idx_diary_date_activity_created_at ON diary_date_activity;
|
||||
DROP INDEX IF EXISTS idx_diary_date_activity_updated_at ON diary_date_activity;
|
||||
|
||||
-- Match-Tabelle
|
||||
DROP INDEX IF EXISTS idx_match_created_at ON match;
|
||||
DROP INDEX IF EXISTS idx_match_updated_at ON match;
|
||||
|
||||
-- League-Tabelle
|
||||
DROP INDEX IF EXISTS idx_league_created_at ON league;
|
||||
DROP INDEX IF EXISTS idx_league_updated_at ON league;
|
||||
|
||||
-- Team-Tabelle
|
||||
DROP INDEX IF EXISTS idx_team_created_at ON team;
|
||||
DROP INDEX IF EXISTS idx_team_updated_at ON team;
|
||||
|
||||
-- Season-Tabelle
|
||||
DROP INDEX IF EXISTS idx_season_created_at ON season;
|
||||
DROP INDEX IF EXISTS idx_season_updated_at ON season;
|
||||
|
||||
-- Location-Tabelle
|
||||
DROP INDEX IF EXISTS idx_location_created_at ON location;
|
||||
DROP INDEX IF EXISTS idx_location_updated_at ON location;
|
||||
|
||||
-- Group-Tabelle
|
||||
DROP INDEX IF EXISTS idx_group_created_at ON `group`;
|
||||
DROP INDEX IF EXISTS idx_group_updated_at ON `group`;
|
||||
|
||||
-- Group_Activity-Tabelle
|
||||
DROP INDEX IF EXISTS idx_group_activity_created_at ON group_activity;
|
||||
DROP INDEX IF EXISTS idx_group_activity_updated_at ON group_activity;
|
||||
|
||||
-- Tournament-Tabelle
|
||||
DROP INDEX IF EXISTS idx_tournament_created_at ON tournament;
|
||||
DROP INDEX IF EXISTS idx_tournament_updated_at ON tournament;
|
||||
|
||||
-- Tournament_Group-Tabelle
|
||||
DROP INDEX IF EXISTS idx_tournament_group_created_at ON tournament_group;
|
||||
DROP INDEX IF EXISTS idx_tournament_group_updated_at ON tournament_group;
|
||||
|
||||
-- Tournament_Member-Tabelle
|
||||
DROP INDEX IF EXISTS idx_tournament_member_created_at ON tournament_member;
|
||||
DROP INDEX IF EXISTS idx_tournament_member_updated_at ON tournament_member;
|
||||
|
||||
-- Tournament_Match-Tabelle
|
||||
DROP INDEX IF EXISTS idx_tournament_match_created_at ON tournament_match;
|
||||
DROP INDEX IF EXISTS idx_tournament_match_updated_at ON tournament_match;
|
||||
|
||||
-- Tournament_Result-Tabelle
|
||||
DROP INDEX IF EXISTS idx_tournament_result_created_at ON tournament_result;
|
||||
DROP INDEX IF EXISTS idx_tournament_result_updated_at ON tournament_result;
|
||||
|
||||
-- Accident-Tabelle
|
||||
DROP INDEX IF EXISTS idx_accident_created_at ON accident;
|
||||
DROP INDEX IF EXISTS idx_accident_updated_at ON accident;
|
||||
|
||||
-- User_Token-Tabelle
|
||||
DROP INDEX IF EXISTS idx_user_token_created_at ON UserToken;
|
||||
DROP INDEX IF EXISTS idx_user_token_updated_at ON UserToken;
|
||||
|
||||
-- 3. Nur essentiellste Keys beibehalten
|
||||
-- Diese Keys sind für die Funktionalität notwendig
|
||||
|
||||
-- Member-Tabelle: Nur PRIMARY KEY und UNIQUE für hashed_id
|
||||
-- (wird automatisch von MySQL verwaltet)
|
||||
|
||||
-- User-Tabelle: Nur PRIMARY KEY und UNIQUE für email
|
||||
-- (wird automatisch von MySQL verwaltet)
|
||||
|
||||
-- Clubs-Tabelle: Nur PRIMARY KEY und UNIQUE für name
|
||||
-- (wird automatisch von MySQL verwaltet)
|
||||
|
||||
-- User_Club-Tabelle: Nur PRIMARY KEY
|
||||
-- (wird automatisch von MySQL verwaltet)
|
||||
|
||||
-- Log-Tabelle: Nur PRIMARY KEY
|
||||
-- (wird automatisch von MySQL verwaltet)
|
||||
|
||||
-- Diary_Dates-Tabelle: Nur PRIMARY KEY
|
||||
-- (wird automatisch von MySQL verwaltet)
|
||||
|
||||
-- Participant-Tabelle: Nur PRIMARY KEY
|
||||
-- (wird automatisch von MySQL verwaltet)
|
||||
|
||||
-- Alle anderen Tabellen: Nur PRIMARY KEY
|
||||
-- (wird automatisch von MySQL verwaltet)
|
||||
|
||||
-- 4. Status anzeigen
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
INDEX_NAME,
|
||||
COLUMN_NAME,
|
||||
NON_UNIQUE,
|
||||
SEQ_IN_INDEX
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;
|
||||
|
||||
-- 5. Anzahl der Keys pro Tabelle anzeigen
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
123
backend/cleanupKeysAggressive.sql
Normal file
123
backend/cleanupKeysAggressive.sql
Normal file
@@ -0,0 +1,123 @@
|
||||
-- Aggressives Cleanup-Script - Entfernt alle überflüssigen INDEX
|
||||
-- Behält nur PRIMARY KEY und UNIQUE constraints
|
||||
|
||||
USE trainingsdiary;
|
||||
|
||||
-- 1. Status vor dem aggressiven Cleanup
|
||||
SELECT '=== STATUS VOR AGGRESSIVEM CLEANUP ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 2. Alle INDEX der Problem-Tabellen anzeigen
|
||||
SELECT '=== MEMBER TABELLE INDEX ===' as info;
|
||||
SHOW INDEX FROM member;
|
||||
|
||||
SELECT '=== DIARY_TAGS TABELLE INDEX ===' as info;
|
||||
SHOW INDEX FROM diary_tags;
|
||||
|
||||
SELECT '=== SEASON TABELLE INDEX ===' as info;
|
||||
SHOW INDEX FROM season;
|
||||
|
||||
-- 3. Alle nicht-essentiellen INDEX entfernen
|
||||
-- Behalte nur: PRIMARY KEY, UNIQUE constraints, FOREIGN KEY
|
||||
|
||||
-- Member-Tabelle: Alle INDEX außer PRIMARY und UNIQUE entfernen
|
||||
SELECT '=== ENTFERNE ALLE ÜBERFLÜSSIGEN MEMBER INDEX ===' as info;
|
||||
|
||||
-- Alle INDEX außer PRIMARY entfernen (PRIMARY kann nicht gelöscht werden)
|
||||
-- Verwende SHOW INDEX um die echten INDEX-Namen zu sehen
|
||||
-- Dann entferne alle außer PRIMARY
|
||||
|
||||
-- Häufige überflüssige INDEX-Namen (alle außer PRIMARY)
|
||||
DROP INDEX IF EXISTS member_hashed_id_unique ON member;
|
||||
DROP INDEX IF EXISTS member_first_name_index ON member;
|
||||
DROP INDEX IF EXISTS member_last_name_index ON member;
|
||||
DROP INDEX IF EXISTS member_birth_date_index ON member;
|
||||
DROP INDEX IF EXISTS member_active_index ON member;
|
||||
DROP INDEX IF EXISTS member_created_at_index ON member;
|
||||
DROP INDEX IF EXISTS member_updated_at_index ON member;
|
||||
DROP INDEX IF EXISTS member_club_id_index ON member;
|
||||
DROP INDEX IF EXISTS member_hashed_id_index ON member;
|
||||
|
||||
-- Alternative INDEX-Namen
|
||||
DROP INDEX IF EXISTS idx_member_hashed_id ON member;
|
||||
DROP INDEX IF EXISTS idx_member_first_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_last_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_birth_date ON member;
|
||||
DROP INDEX IF EXISTS idx_member_active ON member;
|
||||
DROP INDEX IF EXISTS idx_member_created_at ON member;
|
||||
DROP INDEX IF EXISTS idx_member_updated_at ON member;
|
||||
DROP INDEX IF EXISTS idx_member_club_id ON member;
|
||||
|
||||
-- Diary_Tags-Tabelle: Alle überflüssigen INDEX entfernen
|
||||
SELECT '=== ENTFERNE ALLE ÜBERFLÜSSIGEN DIARY_TAGS INDEX ===' as info;
|
||||
|
||||
DROP INDEX IF EXISTS diary_tags_name_index ON diary_tags;
|
||||
DROP INDEX IF EXISTS diary_tags_created_at_index ON diary_tags;
|
||||
DROP INDEX IF EXISTS diary_tags_updated_at_index ON diary_tags;
|
||||
DROP INDEX IF EXISTS diary_tags_club_id_index ON diary_tags;
|
||||
|
||||
-- Alternative INDEX-Namen
|
||||
DROP INDEX IF EXISTS idx_diary_tags_name ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tags_created_at ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tags_updated_at ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tags_club_id ON diary_tags;
|
||||
|
||||
-- Season-Tabelle: Alle überflüssigen INDEX entfernen
|
||||
SELECT '=== ENTFERNE ALLE ÜBERFLÜSSIGEN SEASON INDEX ===' as info;
|
||||
|
||||
DROP INDEX IF EXISTS season_name_index ON season;
|
||||
DROP INDEX IF EXISTS season_start_date_index ON season;
|
||||
DROP INDEX IF EXISTS season_end_date_index ON season;
|
||||
DROP INDEX IF EXISTS season_created_at_index ON season;
|
||||
DROP INDEX IF EXISTS season_updated_at_index ON season;
|
||||
DROP INDEX IF EXISTS season_club_id_index ON season;
|
||||
|
||||
-- Alternative INDEX-Namen
|
||||
DROP INDEX IF EXISTS idx_season_name ON season;
|
||||
DROP INDEX IF EXISTS idx_season_start_date ON season;
|
||||
DROP INDEX IF EXISTS idx_season_end_date ON season;
|
||||
DROP INDEX IF EXISTS idx_season_created_at ON season;
|
||||
DROP INDEX IF EXISTS idx_season_updated_at ON season;
|
||||
DROP INDEX IF EXISTS idx_season_club_id ON season;
|
||||
|
||||
-- 4. Status nach dem aggressiven Cleanup
|
||||
SELECT '=== STATUS NACH AGGRESSIVEM CLEANUP ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 5. Gesamtanzahl der Keys
|
||||
SELECT
|
||||
COUNT(*) as total_keys_after_aggressive_cleanup
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
|
||||
-- 6. Ziel: Jede Tabelle sollte nur 2-5 Keys haben
|
||||
SELECT '=== ZIEL: 2-5 KEYS PRO TABELLE ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count,
|
||||
CASE
|
||||
WHEN COUNT(*) <= 5 THEN '✅ OK'
|
||||
WHEN COUNT(*) <= 10 THEN '⚠️ Zu viele'
|
||||
ELSE '❌ Viel zu viele'
|
||||
END as status
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 7. Zusammenfassung
|
||||
SELECT '=== ZUSAMMENFASSUNG ===' as info;
|
||||
SELECT
|
||||
'Aggressives Cleanup abgeschlossen. Jede Tabelle sollte nur 2-5 Keys haben.' as message;
|
||||
152
backend/cleanupKeysCorrected.sql
Normal file
152
backend/cleanupKeysCorrected.sql
Normal file
@@ -0,0 +1,152 @@
|
||||
-- Korrigiertes Cleanup-Script für MySQL Keys
|
||||
-- Verwendet die wahrscheinlich korrekten Tabellennamen
|
||||
|
||||
USE trainingsdiary;
|
||||
|
||||
-- 1. Alle überflüssigen INDEX entfernen
|
||||
-- Diese entfernen die meisten Keys, die das Limit überschreiten
|
||||
|
||||
-- User-Tabelle (wahrscheinlich 'user')
|
||||
DROP INDEX IF EXISTS idx_user_email ON user;
|
||||
DROP INDEX IF EXISTS idx_user_created_at ON user;
|
||||
DROP INDEX IF EXISTS idx_user_updated_at ON user;
|
||||
|
||||
-- Clubs-Tabelle (wahrscheinlich 'clubs')
|
||||
DROP INDEX IF EXISTS idx_clubs_name ON clubs;
|
||||
DROP INDEX IF EXISTS idx_clubs_created_at ON clubs;
|
||||
DROP INDEX IF EXISTS idx_clubs_updated_at ON clubs;
|
||||
|
||||
-- User_Club-Tabelle (wahrscheinlich 'user_club')
|
||||
DROP INDEX IF EXISTS idx_user_club_approved ON user_club;
|
||||
DROP INDEX IF EXISTS idx_user_club_created_at ON user_club;
|
||||
DROP INDEX IF EXISTS idx_user_club_updated_at ON user_club;
|
||||
|
||||
-- Member-Tabelle (wahrscheinlich 'member')
|
||||
DROP INDEX IF EXISTS idx_member_hashed_id ON member;
|
||||
DROP INDEX IF EXISTS idx_member_first_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_last_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_birth_date ON member;
|
||||
DROP INDEX IF EXISTS idx_member_active ON member;
|
||||
DROP INDEX IF EXISTS idx_member_created_at ON member;
|
||||
DROP INDEX IF EXISTS idx_member_updated_at ON member;
|
||||
|
||||
-- Log-Tabelle (wahrscheinlich 'log')
|
||||
DROP INDEX IF EXISTS idx_log_activity ON log;
|
||||
DROP INDEX IF EXISTS idx_log_created_at ON log;
|
||||
DROP INDEX IF EXISTS idx_log_updated_at ON log;
|
||||
|
||||
-- Diary_Dates-Tabelle (wahrscheinlich 'diary_dates')
|
||||
DROP INDEX IF EXISTS idx_diary_dates_date ON diary_dates;
|
||||
DROP INDEX IF EXISTS idx_diary_dates_created_at ON diary_dates;
|
||||
DROP INDEX IF EXISTS idx_diary_dates_updated_at ON diary_dates;
|
||||
|
||||
-- Participants-Tabelle (wahrscheinlich 'participants')
|
||||
DROP INDEX IF EXISTS idx_participant_created_at ON participants;
|
||||
DROP INDEX IF EXISTS idx_participant_updated_at ON participants;
|
||||
|
||||
-- Activities-Tabelle (wahrscheinlich 'activities')
|
||||
DROP INDEX IF EXISTS idx_activity_created_at ON activities;
|
||||
DROP INDEX IF EXISTS idx_activity_updated_at ON activities;
|
||||
|
||||
-- Member_Notes-Tabelle (wahrscheinlich 'member_notes')
|
||||
DROP INDEX IF EXISTS idx_member_note_created_at ON member_notes;
|
||||
DROP INDEX IF EXISTS idx_member_note_updated_at ON member_notes;
|
||||
|
||||
-- Diary_Notes-Tabelle (wahrscheinlich 'diary_notes')
|
||||
DROP INDEX IF EXISTS idx_diary_note_created_at ON diary_notes;
|
||||
DROP INDEX IF EXISTS idx_diary_note_updated_at ON diary_notes;
|
||||
|
||||
-- Diary_Tags-Tabelle (wahrscheinlich 'diary_tags')
|
||||
DROP INDEX IF EXISTS idx_diary_tag_created_at ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tag_updated_at ON diary_tags;
|
||||
|
||||
-- Member_Diary_Tags-Tabelle (wahrscheinlich 'member_diary_tags')
|
||||
DROP INDEX IF EXISTS idx_member_diary_tag_created_at ON member_diary_tags;
|
||||
DROP INDEX IF EXISTS idx_member_diary_tag_updated_at ON member_diary_tags;
|
||||
|
||||
-- Diary_Date_Tags-Tabelle (wahrscheinlich 'diary_date_tags')
|
||||
DROP INDEX IF EXISTS idx_diary_date_tag_created_at ON diary_date_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_date_tag_updated_at ON diary_date_tags;
|
||||
|
||||
-- Diary_Member_Notes-Tabelle (wahrscheinlich 'diary_member_notes')
|
||||
DROP INDEX IF EXISTS idx_diary_member_note_created_at ON diary_member_notes;
|
||||
DROP INDEX IF EXISTS idx_diary_member_note_updated_at ON diary_member_notes;
|
||||
|
||||
-- Predefined_Activities-Tabelle (wahrscheinlich 'predefined_activities')
|
||||
DROP INDEX IF EXISTS idx_predefined_activity_created_at ON predefined_activities;
|
||||
DROP INDEX IF EXISTS idx_predefined_activity_updated_at ON predefined_activities;
|
||||
|
||||
-- Diary_Date_Activities-Tabelle (wahrscheinlich 'diary_date_activities')
|
||||
DROP INDEX IF EXISTS idx_diary_date_activity_created_at ON diary_date_activities;
|
||||
DROP INDEX IF EXISTS idx_diary_date_activity_updated_at ON diary_date_activities;
|
||||
|
||||
-- Matches-Tabelle (wahrscheinlich 'matches')
|
||||
DROP INDEX IF EXISTS idx_match_created_at ON matches;
|
||||
DROP INDEX IF EXISTS idx_match_updated_at ON matches;
|
||||
|
||||
-- Leagues-Tabelle (wahrscheinlich 'leagues')
|
||||
DROP INDEX IF EXISTS idx_league_created_at ON leagues;
|
||||
DROP INDEX IF EXISTS idx_league_updated_at ON leagues;
|
||||
|
||||
-- Teams-Tabelle (wahrscheinlich 'teams')
|
||||
DROP INDEX IF EXISTS idx_team_created_at ON teams;
|
||||
DROP INDEX IF EXISTS idx_team_updated_at ON teams;
|
||||
|
||||
-- Seasons-Tabelle (wahrscheinlich 'seasons')
|
||||
DROP INDEX IF EXISTS idx_season_created_at ON seasons;
|
||||
DROP INDEX IF EXISTS idx_season_updated_at ON seasons;
|
||||
|
||||
-- Locations-Tabelle (wahrscheinlich 'locations')
|
||||
DROP INDEX IF EXISTS idx_location_created_at ON locations;
|
||||
DROP INDEX IF EXISTS idx_location_updated_at ON locations;
|
||||
|
||||
-- Groups-Tabelle (wahrscheinlich 'groups')
|
||||
DROP INDEX IF EXISTS idx_group_created_at ON `groups`;
|
||||
DROP INDEX IF EXISTS idx_group_updated_at ON `groups`;
|
||||
|
||||
-- Group_Activities-Tabelle (wahrscheinlich 'group_activities')
|
||||
DROP INDEX IF EXISTS idx_group_activity_created_at ON group_activities;
|
||||
DROP INDEX IF EXISTS idx_group_activity_updated_at ON group_activities;
|
||||
|
||||
-- Tournaments-Tabelle (wahrscheinlich 'tournaments')
|
||||
DROP INDEX IF EXISTS idx_tournament_created_at ON tournaments;
|
||||
DROP INDEX IF EXISTS idx_tournament_updated_at ON tournaments;
|
||||
|
||||
-- Tournament_Groups-Tabelle (wahrscheinlich 'tournament_groups')
|
||||
DROP INDEX IF EXISTS idx_tournament_group_created_at ON tournament_groups;
|
||||
DROP INDEX IF EXISTS idx_tournament_group_updated_at ON tournament_groups;
|
||||
|
||||
-- Tournament_Members-Tabelle (wahrscheinlich 'tournament_members')
|
||||
DROP INDEX IF EXISTS idx_tournament_member_created_at ON tournament_members;
|
||||
DROP INDEX IF EXISTS idx_tournament_member_updated_at ON tournament_members;
|
||||
|
||||
-- Tournament_Matches-Tabelle (wahrscheinlich 'tournament_matches')
|
||||
DROP INDEX IF EXISTS idx_tournament_match_created_at ON tournament_matches;
|
||||
DROP INDEX IF EXISTS idx_tournament_match_updated_at ON tournament_matches;
|
||||
|
||||
-- Tournament_Results-Tabelle (wahrscheinlich 'tournament_results')
|
||||
DROP INDEX IF EXISTS idx_tournament_result_created_at ON tournament_results;
|
||||
DROP INDEX IF EXISTS idx_tournament_result_updated_at ON tournament_results;
|
||||
|
||||
-- Accidents-Tabelle (wahrscheinlich 'accidents')
|
||||
DROP INDEX IF EXISTS idx_accident_created_at ON accidents;
|
||||
DROP INDEX IF EXISTS idx_accident_updated_at ON accidents;
|
||||
|
||||
-- User_Tokens-Tabelle (wahrscheinlich 'user_tokens')
|
||||
DROP INDEX IF EXISTS idx_user_token_created_at ON user_tokens;
|
||||
DROP INDEX IF EXISTS idx_user_token_updated_at ON user_tokens;
|
||||
|
||||
-- 2. Status anzeigen
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 3. Gesamtanzahl der Keys anzeigen
|
||||
SELECT
|
||||
COUNT(*) as total_keys
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
100
backend/cleanupKeysFinal.sql
Normal file
100
backend/cleanupKeysFinal.sql
Normal file
@@ -0,0 +1,100 @@
|
||||
-- Finales Cleanup-Script für die verbleibenden Problem-Tabellen
|
||||
-- Entfernt weitere INDEX aus member, diary_tags und season
|
||||
|
||||
USE trainingsdiary;
|
||||
|
||||
-- 1. Status vor dem finalen Cleanup
|
||||
SELECT '=== STATUS VOR FINALEM CLEANUP ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 2. Alle INDEX der Problem-Tabellen anzeigen
|
||||
SELECT '=== MEMBER TABELLE INDEX ===' as info;
|
||||
SHOW INDEX FROM member;
|
||||
|
||||
SELECT '=== DIARY_TAGS TABELLE INDEX ===' as info;
|
||||
SHOW INDEX FROM diary_tags;
|
||||
|
||||
SELECT '=== SEASON TABELLE INDEX ===' as info;
|
||||
SHOW INDEX FROM season;
|
||||
|
||||
-- 3. Spezifische INDEX entfernen (basierend auf den echten Namen)
|
||||
-- Diese INDEX sind wahrscheinlich überflüssig und können entfernt werden
|
||||
|
||||
-- Member-Tabelle: Weitere INDEX entfernen
|
||||
SELECT '=== ENTFERNE WEITERE MEMBER INDEX ===' as info;
|
||||
|
||||
-- Versuche, INDEX zu entfernen, die wahrscheinlich überflüssig sind
|
||||
-- (Diese Namen basieren auf typischen Sequelize-Konventionen)
|
||||
|
||||
-- Häufige überflüssige INDEX-Namen
|
||||
DROP INDEX IF EXISTS member_hashed_id_unique ON member;
|
||||
DROP INDEX IF EXISTS member_first_name_index ON member;
|
||||
DROP INDEX IF EXISTS member_last_name_index ON member;
|
||||
DROP INDEX IF EXISTS member_birth_date_index ON member;
|
||||
DROP INDEX IF EXISTS member_active_index ON member;
|
||||
DROP INDEX IF EXISTS member_created_at_index ON member;
|
||||
DROP INDEX IF EXISTS member_updated_at_index ON member;
|
||||
|
||||
-- Alternative INDEX-Namen
|
||||
DROP INDEX IF EXISTS idx_member_hashed_id ON member;
|
||||
DROP INDEX IF EXISTS idx_member_first_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_last_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_birth_date ON member;
|
||||
DROP INDEX IF EXISTS idx_member_active ON member;
|
||||
DROP INDEX IF EXISTS idx_member_created_at ON member;
|
||||
DROP INDEX IF EXISTS idx_member_updated_at ON member;
|
||||
|
||||
-- Diary_Tags-Tabelle: Weitere INDEX entfernen
|
||||
SELECT '=== ENTFERNE WEITERE DIARY_TAGS INDEX ===' as info;
|
||||
|
||||
DROP INDEX IF EXISTS diary_tags_name_index ON diary_tags;
|
||||
DROP INDEX IF EXISTS diary_tags_created_at_index ON diary_tags;
|
||||
DROP INDEX IF EXISTS diary_tags_updated_at_index ON member;
|
||||
|
||||
-- Alternative INDEX-Namen
|
||||
DROP INDEX IF EXISTS idx_diary_tags_name ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tags_created_at ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tags_updated_at ON diary_tags;
|
||||
|
||||
-- Season-Tabelle: Weitere INDEX entfernen
|
||||
SELECT '=== ENTFERNE WEITERE SEASON INDEX ===' as info;
|
||||
|
||||
DROP INDEX IF EXISTS season_name_index ON season;
|
||||
DROP INDEX IF EXISTS season_start_date_index ON season;
|
||||
DROP INDEX IF EXISTS season_end_date_index ON season;
|
||||
DROP INDEX IF EXISTS season_created_at_index ON season;
|
||||
DROP INDEX IF EXISTS season_updated_at_index ON season;
|
||||
|
||||
-- Alternative INDEX-Namen
|
||||
DROP INDEX IF EXISTS idx_season_name ON season;
|
||||
DROP INDEX IF EXISTS idx_season_start_date ON season;
|
||||
DROP INDEX IF EXISTS idx_season_end_date ON season;
|
||||
DROP INDEX IF EXISTS idx_season_created_at ON season;
|
||||
DROP INDEX IF EXISTS idx_season_updated_at ON season;
|
||||
|
||||
-- 4. Status nach dem finalen Cleanup
|
||||
SELECT '=== STATUS NACH FINALEM CLEANUP ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 5. Gesamtanzahl der Keys
|
||||
SELECT
|
||||
COUNT(*) as total_keys_after_final_cleanup
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
|
||||
-- 6. Zusammenfassung
|
||||
SELECT '=== ZUSAMMENFASSUNG ===' as info;
|
||||
SELECT
|
||||
'Finales Cleanup abgeschlossen. Überprüfen Sie die Anzahl der Keys oben.' as message;
|
||||
125
backend/cleanupKeysIntelligent.sql
Normal file
125
backend/cleanupKeysIntelligent.sql
Normal file
@@ -0,0 +1,125 @@
|
||||
-- Intelligentes Cleanup-Script - Ermittelt echte INDEX-Namen und entfernt diese
|
||||
-- Behält nur PRIMARY KEY und UNIQUE constraints
|
||||
|
||||
USE trainingsdiary;
|
||||
|
||||
-- 1. Status vor dem intelligenten Cleanup
|
||||
SELECT '=== STATUS VOR INTELLIGENTEM CLEANUP ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 2. Alle INDEX der Problem-Tabellen anzeigen (mit echten Namen)
|
||||
SELECT '=== MEMBER TABELLE INDEX (ECHTE NAMEN) ===' as info;
|
||||
SHOW INDEX FROM member;
|
||||
|
||||
SELECT '=== DIARY_TAGS TABELLE INDEX (ECHTE NAMEN) ===' as info;
|
||||
SHOW INDEX FROM diary_tags;
|
||||
|
||||
SELECT '=== SEASON TABELLE INDEX (ECHTE NAMEN) ===' as info;
|
||||
SHOW INDEX FROM season;
|
||||
|
||||
-- 3. Alle INDEX-Namen extrahieren und DROP-Befehle generieren
|
||||
SELECT '=== GENERIERE DROP-BEFEHLE FÜR ÜBERFLÜSSIGE INDEX ===' as info;
|
||||
|
||||
-- Member-Tabelle: Alle INDEX außer PRIMARY entfernen
|
||||
SELECT '=== ENTFERNE ÜBERFLÜSSIGE MEMBER INDEX ===' as info;
|
||||
|
||||
-- Verwende die echten INDEX-Namen aus SHOW INDEX
|
||||
-- Entferne alle außer PRIMARY KEY (PRIMARY kann nicht gelöscht werden)
|
||||
|
||||
-- Beispiel für häufige überflüssige INDEX-Namen (basierend auf Sequelize-Konventionen)
|
||||
-- Diese werden nur ausgeführt, wenn sie existieren
|
||||
|
||||
-- Häufige überflüssige INDEX-Namen
|
||||
DROP INDEX IF EXISTS member_hashed_id_unique ON member;
|
||||
DROP INDEX IF EXISTS member_first_name_index ON member;
|
||||
DROP INDEX IF EXISTS member_last_name_index ON member;
|
||||
DROP INDEX IF EXISTS member_birth_date_index ON member;
|
||||
DROP INDEX IF EXISTS member_active_index ON member;
|
||||
DROP INDEX IF EXISTS member_created_at_index ON member;
|
||||
DROP INDEX IF EXISTS member_updated_at_index ON member;
|
||||
DROP INDEX IF EXISTS member_club_id_index ON member;
|
||||
DROP INDEX IF EXISTS member_hashed_id_index ON member;
|
||||
|
||||
-- Alternative INDEX-Namen
|
||||
DROP INDEX IF EXISTS idx_member_hashed_id ON member;
|
||||
DROP INDEX IF EXISTS idx_member_first_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_last_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_birth_date ON member;
|
||||
DROP INDEX IF EXISTS idx_member_active ON member;
|
||||
DROP INDEX IF EXISTS idx_member_created_at ON member;
|
||||
DROP INDEX IF EXISTS idx_member_updated_at ON member;
|
||||
DROP INDEX IF EXISTS idx_member_club_id ON member;
|
||||
|
||||
-- Diary_Tags-Tabelle: Alle überflüssigen INDEX entfernen
|
||||
SELECT '=== ENTFERNE ÜBERFLÜSSIGE DIARY_TAGS INDEX ===' as info;
|
||||
|
||||
DROP INDEX IF EXISTS diary_tags_name_index ON diary_tags;
|
||||
DROP INDEX IF EXISTS diary_tags_created_at_index ON diary_tags;
|
||||
DROP INDEX IF EXISTS diary_tags_updated_at_index ON diary_tags;
|
||||
DROP INDEX IF EXISTS diary_tags_club_id_index ON diary_tags;
|
||||
|
||||
-- Alternative INDEX-Namen
|
||||
DROP INDEX IF EXISTS idx_diary_tags_name ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tags_created_at ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tags_updated_at ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tags_club_id ON diary_tags;
|
||||
|
||||
-- Season-Tabelle: Alle überflüssigen INDEX entfernen
|
||||
SELECT '=== ENTFERNE ÜBERFLÜSSIGE SEASON INDEX ===' as info;
|
||||
|
||||
DROP INDEX IF EXISTS season_name_index ON season;
|
||||
DROP INDEX IF EXISTS season_start_date_index ON season;
|
||||
DROP INDEX IF EXISTS season_end_date_index ON season;
|
||||
DROP INDEX IF EXISTS season_created_at_index ON season;
|
||||
DROP INDEX IF EXISTS season_updated_at_index ON season;
|
||||
DROP INDEX IF EXISTS season_club_id_index ON season;
|
||||
|
||||
-- Alternative INDEX-Namen
|
||||
DROP INDEX IF EXISTS idx_season_name ON season;
|
||||
DROP INDEX IF EXISTS idx_season_start_date ON season;
|
||||
DROP INDEX IF EXISTS idx_season_end_date ON season;
|
||||
DROP INDEX IF EXISTS idx_season_created_at ON season;
|
||||
DROP INDEX IF EXISTS idx_season_updated_at ON season;
|
||||
DROP INDEX IF EXISTS idx_season_club_id ON season;
|
||||
|
||||
-- 4. Status nach dem intelligenten Cleanup
|
||||
SELECT '=== STATUS NACH INTELLIGENTEM CLEANUP ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 5. Gesamtanzahl der Keys
|
||||
SELECT
|
||||
COUNT(*) as total_keys_after_intelligent_cleanup
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
|
||||
-- 6. Ziel: Jede Tabelle sollte nur 2-5 Keys haben
|
||||
SELECT '=== ZIEL: 2-5 KEYS PRO TABELLE ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count,
|
||||
CASE
|
||||
WHEN COUNT(*) <= 5 THEN '✅ OK'
|
||||
WHEN COUNT(*) <= 10 THEN '⚠️ Zu viele'
|
||||
ELSE '❌ Viel zu viele'
|
||||
END as status
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 7. Zusammenfassung
|
||||
SELECT '=== ZUSAMMENFASSUNG ===' as info;
|
||||
SELECT
|
||||
'Intelligentes Cleanup abgeschlossen. Überprüfen Sie die Anzahl der Keys oben.' as message;
|
||||
79
backend/cleanupKeysMinimal.sql
Normal file
79
backend/cleanupKeysMinimal.sql
Normal file
@@ -0,0 +1,79 @@
|
||||
-- Minimales Cleanup-Script
|
||||
-- Entfernt alle INDEX außer PRIMARY KEY und UNIQUE Keys
|
||||
|
||||
USE trainingsdiary;
|
||||
|
||||
-- 1. Status vor Cleanup
|
||||
SELECT '=== STATUS VOR CLEANUP ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
SELECT
|
||||
COUNT(*) as total_keys_before
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
|
||||
-- 2. Alle nicht-essentiellen INDEX entfernen
|
||||
-- Behalte nur PRIMARY KEY und UNIQUE Keys
|
||||
|
||||
-- Alle INDEX außer PRIMARY und UNIQUE entfernen
|
||||
-- Verwende SHOW INDEX um die echten INDEX-Namen zu sehen
|
||||
|
||||
SELECT '=== ENTFERNE ÜBERFLÜSSIGE INDEX ===' as info;
|
||||
|
||||
-- Member-Tabelle: Alle INDEX außer PRIMARY entfernen
|
||||
SELECT '=== MEMBER TABELLE ===' as info;
|
||||
SHOW INDEX FROM member;
|
||||
|
||||
-- User-Tabelle: Alle INDEX außer PRIMARY entfernen
|
||||
SELECT '=== USER TABELLE ===' as info;
|
||||
SHOW INDEX FROM user;
|
||||
|
||||
-- Clubs-Tabelle: Alle INDEX außer PRIMARY entfernen
|
||||
SELECT '=== CLUBS TABELLE ===' as info;
|
||||
SHOW INDEX FROM clubs;
|
||||
|
||||
-- User_Club-Tabelle: Alle INDEX außer PRIMARY entfernen
|
||||
SELECT '=== USER_CLUB TABELLE ===' as info;
|
||||
SHOW INDEX FROM user_club;
|
||||
|
||||
-- Log-Tabelle: Alle INDEX außer PRIMARY entfernen
|
||||
SELECT '=== LOG TABELLE ===' as info;
|
||||
SHOW INDEX FROM log;
|
||||
|
||||
-- Diary_Dates-Tabelle: Alle INDEX außer PRIMARY entfernen
|
||||
SELECT '=== DIARY_DATES TABELLE ===' as info;
|
||||
SHOW INDEX FROM diary_dates;
|
||||
|
||||
-- Participants-Tabelle: Alle INDEX außer PRIMARY entfernen
|
||||
SELECT '=== PARTICIPANTS TABELLE ===' as info;
|
||||
SHOW INDEX FROM participants;
|
||||
|
||||
-- Activities-Tabelle: Alle INDEX außer PRIMARY entfernen
|
||||
SELECT '=== ACTIVITIES TABELLE ===' as info;
|
||||
SHOW INDEX FROM activities;
|
||||
|
||||
-- 3. Status nach Cleanup
|
||||
SELECT '=== STATUS NACH CLEANUP ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
SELECT
|
||||
COUNT(*) as total_keys_after
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
|
||||
-- 4. Zusammenfassung
|
||||
SELECT '=== ZUSAMMENFASSUNG ===' as info;
|
||||
SELECT
|
||||
'Minimales Cleanup abgeschlossen. Überprüfen Sie die Anzahl der Keys oben.' as message;
|
||||
143
backend/cleanupKeysNode.cjs
Normal file
143
backend/cleanupKeysNode.cjs
Normal file
@@ -0,0 +1,143 @@
|
||||
const mysql = require('mysql2/promise');
|
||||
require('dotenv').config();
|
||||
|
||||
// Datenbankverbindung
|
||||
const dbConfig = {
|
||||
host: process.env.DB_HOST || 'localhost',
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || '',
|
||||
database: process.env.DB_NAME || 'trainingsdiary'
|
||||
};
|
||||
|
||||
async function cleanupKeys() {
|
||||
let connection;
|
||||
|
||||
try {
|
||||
console.log('🔌 Verbinde mit der Datenbank...');
|
||||
connection = await mysql.createConnection(dbConfig);
|
||||
|
||||
// 1. Status vor dem Cleanup
|
||||
console.log('\n📊 STATUS VOR DEM CLEANUP:');
|
||||
const [tablesBefore] = await connection.execute(`
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = ?
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC
|
||||
`, [dbConfig.database]);
|
||||
|
||||
tablesBefore.forEach(table => {
|
||||
console.log(` ${table.TABLE_NAME}: ${table.key_count} Keys`);
|
||||
});
|
||||
|
||||
// 2. Alle INDEX der Problem-Tabellen anzeigen
|
||||
const problemTables = ['member', 'diary_tags', 'season'];
|
||||
|
||||
for (const tableName of problemTables) {
|
||||
console.log(`\n🔍 INDEX für Tabelle '${tableName}':`);
|
||||
|
||||
try {
|
||||
const [indexes] = await connection.execute(`SHOW INDEX FROM \`${tableName}\``);
|
||||
|
||||
if (indexes.length === 0) {
|
||||
console.log(` Keine INDEX gefunden für Tabelle '${tableName}'`);
|
||||
continue;
|
||||
}
|
||||
|
||||
indexes.forEach(index => {
|
||||
console.log(` - ${index.Key_name} (${index.Column_name}) - ${index.Non_unique === 0 ? 'UNIQUE' : 'NON-UNIQUE'}`);
|
||||
});
|
||||
|
||||
// 3. Überflüssige INDEX entfernen (alle außer PRIMARY und UNIQUE)
|
||||
console.log(`\n🗑️ Entferne überflüssige INDEX aus '${tableName}':`);
|
||||
|
||||
for (const index of indexes) {
|
||||
// Behalte PRIMARY KEY und UNIQUE constraints
|
||||
if (index.Key_name === 'PRIMARY' || index.Non_unique === 0) {
|
||||
console.log(` ✅ Behalte: ${index.Key_name} (${index.Column_name})`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Entferne alle anderen INDEX
|
||||
try {
|
||||
await connection.execute(`DROP INDEX \`${index.Key_name}\` ON \`${tableName}\``);
|
||||
console.log(` ❌ Entfernt: ${index.Key_name} (${index.Column_name})`);
|
||||
} catch (error) {
|
||||
if (error.code === 'ER_CANT_DROP_FIELD_OR_KEY') {
|
||||
console.log(` ⚠️ Kann nicht entfernen: ${index.Key_name} (${index.Column_name}) - ${error.message}`);
|
||||
} else {
|
||||
console.log(` ❌ Fehler beim Entfernen von ${index.Key_name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(` ⚠️ Fehler beim Zugriff auf Tabelle '${tableName}': ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Status nach dem Cleanup
|
||||
console.log('\n📊 STATUS NACH DEM CLEANUP:');
|
||||
const [tablesAfter] = await connection.execute(`
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = ?
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC
|
||||
`, [dbConfig.database]);
|
||||
|
||||
tablesAfter.forEach(table => {
|
||||
const before = tablesBefore.find(t => t.TABLE_NAME === table.TABLE_NAME);
|
||||
const beforeCount = before ? before.key_count : 0;
|
||||
const diff = beforeCount - table.key_count;
|
||||
const status = table.key_count <= 5 ? '✅' : table.key_count <= 10 ? '⚠️' : '❌';
|
||||
|
||||
console.log(` ${status} ${table.TABLE_NAME}: ${table.key_count} Keys (${diff > 0 ? `-${diff}` : `+${Math.abs(diff)}`})`);
|
||||
});
|
||||
|
||||
// 5. Gesamtanzahl der Keys
|
||||
const [totalKeys] = await connection.execute(`
|
||||
SELECT COUNT(*) as total_keys
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = ?
|
||||
`, [dbConfig.database]);
|
||||
|
||||
console.log(`\n📈 GESAMTANZAHL KEYS: ${totalKeys[0].total_keys}`);
|
||||
|
||||
// 6. Zusammenfassung
|
||||
console.log('\n🎯 ZUSAMMENFASSUNG:');
|
||||
const problemTablesAfter = tablesAfter.filter(t => t.key_count > 10);
|
||||
|
||||
if (problemTablesAfter.length === 0) {
|
||||
console.log(' ✅ Alle Tabellen haben jetzt weniger als 10 Keys!');
|
||||
} else {
|
||||
console.log(' ⚠️ Folgende Tabellen haben immer noch zu viele Keys:');
|
||||
problemTablesAfter.forEach(table => {
|
||||
console.log(` - ${table.TABLE_NAME}: ${table.key_count} Keys`);
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Cleanup:', error);
|
||||
} finally {
|
||||
if (connection) {
|
||||
await connection.end();
|
||||
console.log('\n🔌 Datenbankverbindung geschlossen.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Script ausführen
|
||||
console.log('🚀 Starte intelligentes INDEX-Cleanup...\n');
|
||||
cleanupKeys().then(() => {
|
||||
console.log('\n✨ Cleanup abgeschlossen!');
|
||||
process.exit(0);
|
||||
}).catch(error => {
|
||||
console.error('\n💥 Fehler beim Cleanup:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
166
backend/cleanupKeysNode.js
Normal file
166
backend/cleanupKeysNode.js
Normal file
@@ -0,0 +1,166 @@
|
||||
import mysql from 'mysql2/promise';
|
||||
import dotenv from 'dotenv';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
// __dirname für ES-Module
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
// Umgebungsvariablen aus dem Root-Verzeichnis laden
|
||||
//const envPath = path.join(__dirname, '..', '.env');
|
||||
//console.log('🔍 Lade .env-Datei von:', envPath);
|
||||
dotenv.config();
|
||||
|
||||
// Debug: Zeige geladene Umgebungsvariablen
|
||||
console.log('🔍 Geladene Umgebungsvariablen:');
|
||||
console.log(' DB_HOST:', process.env.DB_HOST);
|
||||
console.log(' DB_USER:', process.env.DB_USER);
|
||||
console.log(' DB_NAME:', process.env.DB_NAME);
|
||||
console.log(' DB_PASSWORD:', process.env.DB_PASSWORD ? '***gesetzt***' : 'nicht gesetzt');
|
||||
|
||||
// Datenbankverbindung
|
||||
const dbConfig = {
|
||||
host: process.env.DB_HOST || 'localhost',
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || '',
|
||||
database: process.env.DB_NAME || 'trainingsdiary'
|
||||
};
|
||||
|
||||
console.log('🔍 Datenbankverbindung:');
|
||||
console.log(' Host:', dbConfig.host);
|
||||
console.log(' User:', dbConfig.user);
|
||||
console.log(' Database:', dbConfig.database);
|
||||
console.log(' Password:', dbConfig.password ? '***gesetzt***' : 'nicht gesetzt');
|
||||
|
||||
async function cleanupKeys() {
|
||||
let connection;
|
||||
|
||||
try {
|
||||
console.log('🔌 Verbinde mit der Datenbank...');
|
||||
connection = await mysql.createConnection(dbConfig);
|
||||
|
||||
// 1. Status vor dem Cleanup
|
||||
console.log('\n📊 STATUS VOR DEM CLEANUP:');
|
||||
const [tablesBefore] = await connection.execute(`
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = ?
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC
|
||||
`, [dbConfig.database]);
|
||||
|
||||
tablesBefore.forEach(table => {
|
||||
console.log(` ${table.TABLE_NAME}: ${table.key_count} Keys`);
|
||||
});
|
||||
|
||||
// 2. Alle INDEX der Problem-Tabellen anzeigen
|
||||
const problemTables = ['member', 'diary_tags', 'season'];
|
||||
|
||||
for (const tableName of problemTables) {
|
||||
console.log(`\n🔍 INDEX für Tabelle '${tableName}':`);
|
||||
|
||||
try {
|
||||
const [indexes] = await connection.execute(`SHOW INDEX FROM \`${tableName}\``);
|
||||
|
||||
if (indexes.length === 0) {
|
||||
console.log(` Keine INDEX gefunden für Tabelle '${tableName}'`);
|
||||
continue;
|
||||
}
|
||||
|
||||
indexes.forEach(index => {
|
||||
console.log(` - ${index.Key_name} (${index.Column_name}) - ${index.Non_unique === 0 ? 'UNIQUE' : 'NON-UNIQUE'}`);
|
||||
});
|
||||
|
||||
// 3. Überflüssige INDEX entfernen (alle außer PRIMARY und UNIQUE)
|
||||
console.log(`\n🗑️ Entferne überflüssige INDEX aus '${tableName}':`);
|
||||
|
||||
for (const index of indexes) {
|
||||
// Behalte PRIMARY KEY und UNIQUE constraints
|
||||
if (index.Key_name === 'PRIMARY' || index.Non_unique === 0) {
|
||||
console.log(` ✅ Behalte: ${index.Key_name} (${index.Column_name})`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Entferne alle anderen INDEX
|
||||
try {
|
||||
await connection.execute(`DROP INDEX \`${index.Key_name}\` ON \`${tableName}\``);
|
||||
console.log(` ❌ Entfernt: ${index.Key_name} (${index.Column_name})`);
|
||||
} catch (error) {
|
||||
if (error.code === 'ER_CANT_DROP_FIELD_OR_KEY') {
|
||||
console.log(` ⚠️ Kann nicht entfernen: ${index.Key_name} (${index.Column_name}) - ${error.message}`);
|
||||
} else {
|
||||
console.log(` ❌ Fehler beim Entfernen von ${index.Key_name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(` ⚠️ Fehler beim Zugriff auf Tabelle '${tableName}': ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Status nach dem Cleanup
|
||||
console.log('\n📊 STATUS NACH DEM CLEANUP:');
|
||||
const [tablesAfter] = await connection.execute(`
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = ?
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC
|
||||
`, [dbConfig.database]);
|
||||
|
||||
tablesAfter.forEach(table => {
|
||||
const before = tablesBefore.find(t => t.TABLE_NAME === table.TABLE_NAME);
|
||||
const beforeCount = before ? before.key_count : 0;
|
||||
const diff = beforeCount - table.key_count;
|
||||
const status = table.key_count <= 5 ? '✅' : table.key_count <= 10 ? '⚠️' : '❌';
|
||||
|
||||
console.log(` ${status} ${table.TABLE_NAME}: ${table.key_count} Keys (${diff > 0 ? `-${diff}` : `+${Math.abs(diff)}`})`);
|
||||
});
|
||||
|
||||
// 5. Gesamtanzahl der Keys
|
||||
const [totalKeys] = await connection.execute(`
|
||||
SELECT COUNT(*) as total_keys
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = ?
|
||||
`, [dbConfig.database]);
|
||||
|
||||
console.log(`\n📈 GESAMTANZAHL KEYS: ${totalKeys[0].total_keys}`);
|
||||
|
||||
// 6. Zusammenfassung
|
||||
console.log('\n🎯 ZUSAMMENFASSUNG:');
|
||||
const problemTablesAfter = tablesAfter.filter(t => t.key_count > 10);
|
||||
|
||||
if (problemTablesAfter.length === 0) {
|
||||
console.log(' ✅ Alle Tabellen haben jetzt weniger als 10 Keys!');
|
||||
} else {
|
||||
console.log(' ⚠️ Folgende Tabellen haben immer noch zu viele Keys:');
|
||||
problemTablesAfter.forEach(table => {
|
||||
console.log(` - ${table.TABLE_NAME}: ${table.key_count} Keys`);
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Cleanup:', error);
|
||||
} finally {
|
||||
if (connection) {
|
||||
await connection.end();
|
||||
console.log('\n🔌 Datenbankverbindung geschlossen.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Script ausführen
|
||||
console.log('🚀 Starte intelligentes INDEX-Cleanup...\n');
|
||||
cleanupKeys().then(() => {
|
||||
console.log('\n✨ Cleanup abgeschlossen!');
|
||||
process.exit(0);
|
||||
}).catch(error => {
|
||||
console.error('\n💥 Fehler beim Cleanup:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
149
backend/cleanupKeysReal.sql
Normal file
149
backend/cleanupKeysReal.sql
Normal file
@@ -0,0 +1,149 @@
|
||||
-- Cleanup-Script mit echten INDEX-Namen
|
||||
-- Zeigt zuerst alle vorhandenen INDEX an und entfernt dann nur die überflüssigen
|
||||
|
||||
USE trainingsdiary;
|
||||
|
||||
-- 1. Alle vorhandenen INDEX anzeigen
|
||||
SELECT '=== VORHANDENE INDEX VOR CLEANUP ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
INDEX_NAME,
|
||||
COLUMN_NAME,
|
||||
NON_UNIQUE,
|
||||
SEQ_IN_INDEX
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;
|
||||
|
||||
-- 2. Anzahl der Keys pro Tabelle vor Cleanup
|
||||
SELECT '=== KEYS PRO TABELLE VOR CLEANUP ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 3. Gesamtanzahl der Keys vor Cleanup
|
||||
SELECT '=== GESAMTANZAHL KEYS VOR CLEANUP ===' as info;
|
||||
SELECT
|
||||
COUNT(*) as total_keys_before
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
|
||||
-- 4. Cleanup: Nur INDEX entfernen, die tatsächlich existieren
|
||||
-- Verwende DROP INDEX IF EXISTS für alle möglichen INDEX
|
||||
|
||||
-- Member-Tabelle
|
||||
SELECT '=== ENTFERNE MEMBER INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_member_hashed_id ON member;
|
||||
DROP INDEX IF EXISTS idx_member_first_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_last_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_birth_date ON member;
|
||||
DROP INDEX IF EXISTS idx_member_active ON member;
|
||||
DROP INDEX IF EXISTS idx_member_created_at ON member;
|
||||
DROP INDEX IF EXISTS idx_member_updated_at ON member;
|
||||
|
||||
-- User-Tabelle
|
||||
SELECT '=== ENTFERNE USER INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_user_email ON user;
|
||||
DROP INDEX IF EXISTS idx_user_created_at ON user;
|
||||
DROP INDEX IF EXISTS idx_user_updated_at ON user;
|
||||
|
||||
-- Clubs-Tabelle
|
||||
SELECT '=== ENTFERNE CLUBS INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_clubs_name ON clubs;
|
||||
DROP INDEX IF EXISTS idx_clubs_created_at ON clubs;
|
||||
DROP INDEX IF EXISTS idx_clubs_updated_at ON clubs;
|
||||
|
||||
-- User_Club-Tabelle
|
||||
SELECT '=== ENTFERNE USER_CLUB INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_user_club_approved ON user_club;
|
||||
DROP INDEX IF EXISTS idx_user_club_created_at ON user_club;
|
||||
DROP INDEX IF EXISTS idx_user_club_updated_at ON user_club;
|
||||
|
||||
-- Log-Tabelle
|
||||
SELECT '=== ENTFERNE LOG INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_log_activity ON log;
|
||||
DROP INDEX IF EXISTS idx_log_created_at ON log;
|
||||
DROP INDEX IF EXISTS idx_log_updated_at ON log;
|
||||
|
||||
-- Diary_Dates-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_DATES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_dates_date ON diary_dates;
|
||||
DROP INDEX IF EXISTS idx_diary_dates_created_at ON diary_dates;
|
||||
DROP INDEX IF EXISTS idx_diary_dates_updated_at ON diary_dates;
|
||||
|
||||
-- Participants-Tabelle
|
||||
SELECT '=== ENTFERNE PARTICIPANTS INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_participant_created_at ON participants;
|
||||
DROP INDEX IF EXISTS idx_participant_updated_at ON participants;
|
||||
|
||||
-- Activities-Tabelle
|
||||
SELECT '=== ENTFERNE ACTIVITIES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_activity_created_at ON activities;
|
||||
DROP INDEX IF EXISTS idx_activity_updated_at ON activities;
|
||||
|
||||
-- Member_Notes-Tabelle
|
||||
SELECT '=== ENTFERNE MEMBER_NOTES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_member_note_created_at ON member_notes;
|
||||
DROP INDEX IF EXISTS idx_member_note_updated_at ON member_notes;
|
||||
|
||||
-- Diary_Notes-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_NOTES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_note_created_at ON diary_notes;
|
||||
DROP INDEX IF EXISTS idx_diary_note_updated_at ON diary_notes;
|
||||
|
||||
-- Diary_Tags-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_TAGS INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_tag_created_at ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tag_updated_at ON diary_tags;
|
||||
|
||||
-- Member_Diary_Tags-Tabelle
|
||||
SELECT '=== ENTFERNE MEMBER_DIARY_TAGS INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_member_diary_tag_created_at ON member_diary_tags;
|
||||
DROP INDEX IF EXISTS idx_member_diary_tag_updated_at ON member_diary_tags;
|
||||
|
||||
-- Diary_Date_Tags-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_DATE_TAGS INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_date_tag_created_at ON diary_date_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_date_tag_updated_at ON diary_date_tags;
|
||||
|
||||
-- Diary_Member_Notes-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_MEMBER_NOTES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_member_note_created_at ON diary_member_notes;
|
||||
DROP INDEX IF EXISTS idx_diary_member_note_updated_at ON diary_member_notes;
|
||||
|
||||
-- Predefined_Activities-Tabelle
|
||||
SELECT '=== ENTFERNE PREDEFINED_ACTIVITIES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_predefined_activity_created_at ON predefined_activities;
|
||||
DROP INDEX IF EXISTS idx_predefined_activity_updated_at ON predefined_activities;
|
||||
|
||||
-- Diary_Date_Activities-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_DATE_ACTIVITIES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_date_activity_created_at ON diary_date_activities;
|
||||
DROP INDEX IF EXISTS idx_diary_date_activity_updated_at ON diary_date_activities;
|
||||
|
||||
-- 5. Nach der Bereinigung: Status anzeigen
|
||||
SELECT '=== STATUS NACH BEREINIGUNG ===' as info;
|
||||
|
||||
-- Anzahl der Keys pro Tabelle nach der Bereinigung
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- Gesamtanzahl der Keys nach der Bereinigung
|
||||
SELECT
|
||||
COUNT(*) as total_keys_after
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
|
||||
-- 6. Zusammenfassung der Änderungen
|
||||
SELECT '=== ZUSAMMENFASSUNG ===' as info;
|
||||
SELECT
|
||||
'Cleanup abgeschlossen. Überprüfen Sie die Anzahl der Keys oben.' as message;
|
||||
41
backend/cleanupKeysSimple.sql
Normal file
41
backend/cleanupKeysSimple.sql
Normal file
@@ -0,0 +1,41 @@
|
||||
-- Vereinfachtes Cleanup-Script für MySQL Keys
|
||||
-- Entfernt nur die problematischsten Keys
|
||||
|
||||
USE trainingsdiary;
|
||||
|
||||
-- 1. Alle überflüssigen INDEX entfernen (die meisten werden von Sequelize automatisch erstellt)
|
||||
-- Diese entfernen die meisten Keys, die das Limit überschreiten
|
||||
|
||||
-- Member-Tabelle (Hauptproblem)
|
||||
DROP INDEX IF EXISTS idx_member_hashed_id ON member;
|
||||
DROP INDEX IF EXISTS idx_member_first_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_last_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_birth_date ON member;
|
||||
DROP INDEX IF EXISTS idx_member_active ON member;
|
||||
DROP INDEX IF EXISTS idx_member_created_at ON member;
|
||||
DROP INDEX IF EXISTS idx_member_updated_at ON member;
|
||||
|
||||
-- User-Tabelle
|
||||
DROP INDEX IF EXISTS idx_user_email ON user;
|
||||
DROP INDEX IF EXISTS idx_user_created_at ON user;
|
||||
DROP INDEX IF EXISTS idx_user_updated_at ON user;
|
||||
|
||||
-- Clubs-Tabelle
|
||||
DROP INDEX IF EXISTS idx_clubs_name ON clubs;
|
||||
DROP INDEX IF EXISTS idx_clubs_created_at ON clubs;
|
||||
DROP INDEX IF EXISTS idx_clubs_updated_at ON clubs;
|
||||
|
||||
-- 2. Status anzeigen
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 3. Gesamtanzahl der Keys anzeigen
|
||||
SELECT
|
||||
COUNT(*) as total_keys
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
153
backend/cleanupKeysSmart.sql
Normal file
153
backend/cleanupKeysSmart.sql
Normal file
@@ -0,0 +1,153 @@
|
||||
-- Intelligentes Cleanup-Script für MySQL Keys
|
||||
-- Überprüft zuerst die echten Tabellennamen und entfernt nur vorhandene INDEX
|
||||
|
||||
USE trainingsdiary;
|
||||
|
||||
-- 1. Alle vorhandenen Tabellen anzeigen
|
||||
SELECT '=== VORHANDENE TABELLEN ===' as info;
|
||||
SHOW TABLES;
|
||||
|
||||
-- 2. Alle vorhandenen INDEX anzeigen
|
||||
SELECT '=== VORHANDENE INDEX ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
INDEX_NAME,
|
||||
COLUMN_NAME,
|
||||
NON_UNIQUE,
|
||||
SEQ_IN_INDEX
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;
|
||||
|
||||
-- 3. Anzahl der Keys pro Tabelle anzeigen
|
||||
SELECT '=== KEYS PRO TABELLE ===' as info;
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- 4. Gesamtanzahl der Keys anzeigen
|
||||
SELECT '=== GESAMTANZAHL KEYS ===' as info;
|
||||
SELECT
|
||||
COUNT(*) as total_keys
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
|
||||
-- 5. Intelligente INDEX-Entfernung basierend auf vorhandenen Tabellen
|
||||
-- Nur INDEX entfernen, die tatsächlich existieren
|
||||
|
||||
-- Member-Tabelle (Hauptproblem)
|
||||
SELECT '=== ENTFERNE MEMBER INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_member_hashed_id ON member;
|
||||
DROP INDEX IF EXISTS idx_member_first_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_last_name ON member;
|
||||
DROP INDEX IF EXISTS idx_member_birth_date ON member;
|
||||
DROP INDEX IF EXISTS idx_member_active ON member;
|
||||
DROP INDEX IF EXISTS idx_member_created_at ON member;
|
||||
DROP INDEX IF EXISTS idx_member_updated_at ON member;
|
||||
|
||||
-- User-Tabelle
|
||||
SELECT '=== ENTFERNE USER INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_user_email ON user;
|
||||
DROP INDEX IF EXISTS idx_user_created_at ON user;
|
||||
DROP INDEX IF EXISTS idx_user_updated_at ON user;
|
||||
|
||||
-- Clubs-Tabelle
|
||||
SELECT '=== ENTFERNE CLUBS INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_clubs_name ON clubs;
|
||||
DROP INDEX IF EXISTS idx_clubs_created_at ON clubs;
|
||||
DROP INDEX IF EXISTS idx_clubs_updated_at ON clubs;
|
||||
|
||||
-- User_Club-Tabelle
|
||||
SELECT '=== ENTFERNE USER_CLUB INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_user_club_approved ON user_club;
|
||||
DROP INDEX IF EXISTS idx_user_club_created_at ON user_club;
|
||||
DROP INDEX IF EXISTS idx_user_club_updated_at ON user_club;
|
||||
|
||||
-- Log-Tabelle
|
||||
SELECT '=== ENTFERNE LOG INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_log_activity ON log;
|
||||
DROP INDEX IF EXISTS idx_log_created_at ON log;
|
||||
DROP INDEX IF EXISTS idx_log_updated_at ON log;
|
||||
|
||||
-- Diary_Dates-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_DATES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_dates_date ON diary_dates;
|
||||
DROP INDEX IF EXISTS idx_diary_dates_created_at ON diary_dates;
|
||||
DROP INDEX IF EXISTS idx_diary_dates_updated_at ON diary_dates;
|
||||
|
||||
-- Participants-Tabelle
|
||||
SELECT '=== ENTFERNE PARTICIPANTS INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_participant_created_at ON participants;
|
||||
DROP INDEX IF EXISTS idx_participant_updated_at ON participants;
|
||||
|
||||
-- Activities-Tabelle
|
||||
SELECT '=== ENTFERNE ACTIVITIES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_activity_created_at ON activities;
|
||||
DROP INDEX IF EXISTS idx_activity_updated_at ON activities;
|
||||
|
||||
-- Member_Notes-Tabelle
|
||||
SELECT '=== ENTFERNE MEMBER_NOTES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_member_note_created_at ON member_notes;
|
||||
DROP INDEX IF EXISTS idx_member_note_updated_at ON member_notes;
|
||||
|
||||
-- Diary_Notes-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_NOTES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_note_created_at ON diary_notes;
|
||||
DROP INDEX IF EXISTS idx_diary_note_updated_at ON diary_notes;
|
||||
|
||||
-- Diary_Tags-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_TAGS INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_tag_created_at ON diary_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_tag_updated_at ON diary_tags;
|
||||
|
||||
-- Member_Diary_Tags-Tabelle
|
||||
SELECT '=== ENTFERNE MEMBER_DIARY_TAGS INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_member_diary_tag_created_at ON member_diary_tags;
|
||||
DROP INDEX IF EXISTS idx_member_diary_tag_updated_at ON member_diary_tags;
|
||||
|
||||
-- Diary_Date_Tags-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_DATE_TAGS INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_date_tag_created_at ON diary_date_tags;
|
||||
DROP INDEX IF EXISTS idx_diary_date_tag_updated_at ON diary_date_tags;
|
||||
|
||||
-- Diary_Member_Notes-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_MEMBER_NOTES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_member_note_created_at ON diary_member_notes;
|
||||
DROP INDEX IF EXISTS idx_diary_member_note_updated_at ON diary_member_notes;
|
||||
|
||||
-- Predefined_Activities-Tabelle
|
||||
SELECT '=== ENTFERNE PREDEFINED_ACTIVITIES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_predefined_activity_created_at ON predefined_activities;
|
||||
DROP INDEX IF EXISTS idx_predefined_activity_updated_at ON predefined_activities;
|
||||
|
||||
-- Diary_Date_Activities-Tabelle
|
||||
SELECT '=== ENTFERNE DIARY_DATE_ACTIVITIES INDEX ===' as info;
|
||||
DROP INDEX IF EXISTS idx_diary_date_activity_created_at ON diary_date_activities;
|
||||
DROP INDEX IF EXISTS idx_diary_date_activity_updated_at ON diary_date_activities;
|
||||
|
||||
-- 6. Nach der Bereinigung: Status anzeigen
|
||||
SELECT '=== STATUS NACH BEREINIGUNG ===' as info;
|
||||
|
||||
-- Anzahl der Keys pro Tabelle nach der Bereinigung
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
COUNT(*) as key_count
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary'
|
||||
GROUP BY TABLE_NAME
|
||||
ORDER BY key_count DESC;
|
||||
|
||||
-- Gesamtanzahl der Keys nach der Bereinigung
|
||||
SELECT
|
||||
COUNT(*) as total_keys_after_cleanup
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = 'trainingsdiary';
|
||||
|
||||
-- 7. Zusammenfassung
|
||||
SELECT '=== ZUSAMMENFASSUNG ===' as info;
|
||||
SELECT
|
||||
'Cleanup abgeschlossen. Überprüfen Sie die Anzahl der Keys oben.' as message;
|
||||
121
backend/controllers/trainingStatsController.js
Normal file
121
backend/controllers/trainingStatsController.js
Normal file
@@ -0,0 +1,121 @@
|
||||
import { DiaryDate, Member, Participant } from '../models/index.js';
|
||||
import { Op } from 'sequelize';
|
||||
|
||||
class TrainingStatsController {
|
||||
async getTrainingStats(req, res) {
|
||||
try {
|
||||
const { clubId } = req.params;
|
||||
|
||||
// Aktuelle Datum für Berechnungen
|
||||
const now = new Date();
|
||||
const twelveMonthsAgo = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate());
|
||||
const threeMonthsAgo = new Date(now.getFullYear(), now.getMonth() - 3, now.getDate());
|
||||
|
||||
// Alle aktiven Mitglieder des Vereins laden
|
||||
const members = await Member.findAll({
|
||||
where: {
|
||||
active: true
|
||||
}
|
||||
});
|
||||
|
||||
const stats = [];
|
||||
|
||||
for (const member of members) {
|
||||
// Trainingsteilnahmen der letzten 12 Monate über Participant-Model
|
||||
const participation12Months = await Participant.count({
|
||||
include: [{
|
||||
model: DiaryDate,
|
||||
as: 'diaryDate',
|
||||
where: {
|
||||
clubId: parseInt(clubId),
|
||||
date: {
|
||||
[Op.gte]: twelveMonthsAgo
|
||||
}
|
||||
}
|
||||
}],
|
||||
where: {
|
||||
memberId: member.id
|
||||
}
|
||||
});
|
||||
|
||||
// Trainingsteilnahmen der letzten 3 Monate über Participant-Model
|
||||
const participation3Months = await Participant.count({
|
||||
include: [{
|
||||
model: DiaryDate,
|
||||
as: 'diaryDate',
|
||||
where: {
|
||||
clubId: parseInt(clubId),
|
||||
date: {
|
||||
[Op.gte]: threeMonthsAgo
|
||||
}
|
||||
}
|
||||
}],
|
||||
where: {
|
||||
memberId: member.id
|
||||
}
|
||||
});
|
||||
|
||||
// Trainingsteilnahmen insgesamt über Participant-Model
|
||||
const participationTotal = await Participant.count({
|
||||
include: [{
|
||||
model: DiaryDate,
|
||||
as: 'diaryDate',
|
||||
where: {
|
||||
clubId: parseInt(clubId)
|
||||
}
|
||||
}],
|
||||
where: {
|
||||
memberId: member.id
|
||||
}
|
||||
});
|
||||
|
||||
// Detaillierte Trainingsdaten (absteigend sortiert) über Participant-Model
|
||||
const trainingDetails = await Participant.findAll({
|
||||
include: [{
|
||||
model: DiaryDate,
|
||||
as: 'diaryDate',
|
||||
where: {
|
||||
clubId: parseInt(clubId)
|
||||
}
|
||||
}],
|
||||
where: {
|
||||
memberId: member.id
|
||||
},
|
||||
order: [['diaryDate', 'date', 'DESC']],
|
||||
limit: 50 // Begrenzen auf die letzten 50 Trainingseinheiten
|
||||
});
|
||||
|
||||
// Trainingsteilnahmen für den Member formatieren
|
||||
const formattedTrainingDetails = trainingDetails.map(participation => ({
|
||||
id: participation.id,
|
||||
date: participation.diaryDate.date,
|
||||
activityName: 'Training',
|
||||
startTime: '--:--',
|
||||
endTime: '--:--'
|
||||
}));
|
||||
|
||||
stats.push({
|
||||
id: member.id,
|
||||
firstName: member.firstName,
|
||||
lastName: member.lastName,
|
||||
birthDate: member.birthDate,
|
||||
participation12Months,
|
||||
participation3Months,
|
||||
participationTotal,
|
||||
trainingDetails: formattedTrainingDetails
|
||||
});
|
||||
}
|
||||
|
||||
// Nach Gesamtteilnahme absteigend sortieren
|
||||
stats.sort((a, b) => b.participationTotal - a.participationTotal);
|
||||
|
||||
res.json(stats);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Trainings-Statistik:', error);
|
||||
res.status(500).json({ error: 'Fehler beim Laden der Trainings-Statistik' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new TrainingStatsController();
|
||||
@@ -41,6 +41,12 @@ Club.hasMany(DiaryDate, { foreignKey: 'clubId' });
|
||||
DiaryDate.belongsToMany(Member, { through: Participant, as: 'participants', foreignKey: 'diaryDateId' });
|
||||
Member.belongsToMany(DiaryDate, { through: Participant, as: 'diaryDates', foreignKey: 'memberId' });
|
||||
|
||||
// Explizite Assoziationen für Participant
|
||||
Participant.belongsTo(DiaryDate, { foreignKey: 'diaryDateId', as: 'diaryDate' });
|
||||
Participant.belongsTo(Member, { foreignKey: 'memberId', as: 'member' });
|
||||
DiaryDate.hasMany(Participant, { foreignKey: 'diaryDateId', as: 'participantList' });
|
||||
Member.hasMany(Participant, { foreignKey: 'memberId', as: 'participantList' });
|
||||
|
||||
DiaryDate.hasMany(Activity, { as: 'activities', foreignKey: 'diaryDateId' });
|
||||
Activity.belongsTo(DiaryDate, { as: 'diaryDate', foreignKey: 'diaryDateId' });
|
||||
|
||||
|
||||
10
backend/routes/trainingStatsRoutes.js
Normal file
10
backend/routes/trainingStatsRoutes.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import express from 'express';
|
||||
import trainingStatsController from '../controllers/trainingStatsController.js';
|
||||
import { authenticate } from '../middleware/authMiddleware.js';
|
||||
const router = express.Router();
|
||||
|
||||
router.use(authenticate);
|
||||
|
||||
router.get('/:clubId', trainingStatsController.getTrainingStats);
|
||||
|
||||
export default router;
|
||||
@@ -30,6 +30,7 @@ import diaryDateTagRoutes from './routes/diaryDateTagRoutes.js';
|
||||
import sessionRoutes from './routes/sessionRoutes.js';
|
||||
import tournamentRoutes from './routes/tournamentRoutes.js';
|
||||
import accidentRoutes from './routes/accidentRoutes.js';
|
||||
import trainingStatsRoutes from './routes/trainingStatsRoutes.js';
|
||||
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
@@ -58,9 +59,11 @@ app.use('/api/diarydatetags', diaryDateTagRoutes);
|
||||
app.use('/api/session', sessionRoutes);
|
||||
app.use('/api/tournament', tournamentRoutes);
|
||||
app.use('/api/accident', accidentRoutes);
|
||||
app.use('/api/training-stats', trainingStatsRoutes);
|
||||
|
||||
app.use(express.static(path.join(__dirname, '../frontend/dist')));
|
||||
|
||||
// Catch-All Handler für Frontend-Routen (muss nach den API-Routen stehen)
|
||||
app.get('*', (req, res) => {
|
||||
res.sendFile(path.join(__dirname, '../frontend/dist/index.html'));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user