Compare commits

..

4 Commits

Author SHA1 Message Date
Sven Riwoldt 9eeea3eed1 Typst begonnen 2026-07-21 10:01:38 +02:00
Sven Riwoldt 8ddd29a1fc Bruno Cookies 2026-07-20 08:30:10 +02:00
Sven Riwoldt f7265676a8 SQL erweitert 2026-07-15 14:37:50 +02:00
Sven Riwoldt eec5516e14 SQL erweitert und Bruno hinzugefügt 2026-07-06 11:32:17 +02:00
13 changed files with 495 additions and 0 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

+68
View File
@@ -585,6 +585,74 @@ To extract data from a database table, use the SELECT statement with the FROM cl
SELECT column1, column2, column3 FROM table_name
#####################################################
## Mathematical Columns
### Verfügbare Tabellen und Spalten:
products: id, price, quantity
Erstellen Sie eine Abfrage, die Folgendes berechnet:
1. Eine Spalte namens total_value, die den Preis mit der Menge multipliziert und eine feste Versandpauschale von 15 hinzufügt
2. Eine Spalte namens discounted_value, die:
- Zuerst den Preis mit der Menge multipliziert
- Dann einen 20%-Rabatt anwendet (multipliziert mit 0.8)
- Schließlich eine feste Versandpauschale von 10 hinzufügt
Versuchen Sie, Klammern angemessen zu verwenden, um sicherzustellen, dass die Berechnungen in der richtigen Reihenfolge durchgeführt werden!
select (price * quantity + 15) as total_value, (price * quantity * 0.8 + 10) as discounted_value from products
## The Modulo Operation
Der Modulo-Operator % gibt den Rest an, der nach der Division einer Zahl durch eine andere übrig bleibt.
dividend % divisor
dividend: Die Zahl, die geteilt wird.
divisor: Die Zahl, durch die der Dividend geteilt wird.
Zum Beispiel
10 % 3
Hier wird 10 durch 3 geteilt. Die 3 passt dreimal in die 10, mit einem Rest von 1. Daher wird result 1 sein.
Normalerweise wird Modulo verwendet, um zu prüfen, ob eine Zahl gerade oder ungerade ist:
Wenn eine Zahl gerade ist, lässt die Division durch 2 einen Rest von 0.
Wenn eine Zahl ungerade ist, lässt die Division durch 2 einen Rest von 1.
Finden Sie zum Beispiel Zeilen mit geraden Nummern:
SELECT * FROM table WHERE id % 2 = 0;
Oder zum Durchlaufen von Werten:
number % 12 (gibt 0-11 zurück)
number % 8 (gibt 0-7 zurück)
Gruppieren Sie zum Beispiel Elemente in 5er-Gruppen:
SELECT item_number % 5 as group_number FROM inventory;
Welche Abfrage wählt nur ungerade Zeilen aus?
SELECT * FROM users WHERE id % 2 = 1;
Vervollständigen Sie die Abfrage, um Produkte in 4er-Gruppen zu gruppieren:
SELECT product_id % 4 as group_num FROM products; -- hier wurde nur % hinzugefügt
Welchen Wertebereich kann number % 7 zurückgeben?
0 through 6
Der Rest bei der Division durch 7 ist immer kleiner als 7 und reicht von 0 bis 6.
#####################################################
+5
View File
@@ -0,0 +1,5 @@
# Übersetzung LaTeX -- Typst
https://qwinsi.github.io/tex2typst-webapp/cheat-sheet.html
# Tabellen
+101
View File
@@ -0,0 +1,101 @@
# Bruno: Session zur i-doit aufbauen
In Bruno bekommst du eine "Session" über eine Kombination aus **Environment-Variablen** und dem **API-Key-Login von i-doit**. i-doit selbst nutzt keine klassischen Cookie-Sessions für die JSON-RPC-API, sondern authentifiziert jeden Request per Header der "Session-Charakter" kommt also über gespeicherte Variablen, die alle Requests teilen.
## 1. Environment anlegen
Anlegen eines Environment `demo-idoit` mit:
```
base_url: https://demo.i-doit.com/src/jsonrpc.php
apikey: c1ia5q
username: admin
password: admin
```
![](idoit01.png)
![](idoit02.png)
## 2. Login-Request (holt die Session-ID)
i-doit unterstützt eine echte Session über `idoit.login`. Der Response liefert einen `X-RPC-Auth-Session`-Header, den du für Folge-Requests wiederverwendest.
**POST** `{{base_url}}`
Headers:
```
Content-Type: application/json
X-RPC-Auth-Username: {{username}}
X-RPC-Auth-Password: {{password}}
```
![](idoit03.png)
Body (JSON):
```json
{
"version": "2.0",
"method": "idoit.login",
"params": { "apikey": "{{apikey}}" },
"id": 1
}
```
Im **Script → Post Response** die Session-ID in eine Variable schreiben:
```javascript
bru.setEnvVar("session_id", res.getHeader("x-rpc-auth-session"));
```
## 3. Folge-Requests mit der Session
Alle weiteren Requests nutzen dann statt Username/Passwort nur noch:
```
Content-Type: application/json
X-RPC-Auth-Session: {{session_id}}
```
Body z. B. für eine Objektabfrage:
```json
{
"version": "2.0",
"method": "cmdb.objects.read",
"params": { "apikey": "{{apikey}}", "filter": { "type": 5 } },
"id": 1
}
```
## 4. Logout (optional)
```json
{ "version": "2.0", "method": "idoit.logout", "params": { "apikey": "{{apikey}}" }, "id": 1 }
```
mit Header `X-RPC-Auth-Session: {{session_id}}`.
---
**Kernpunkt:** Die Session-ID aus dem Login-Response wird per Post-Response-Script als Environment-Variable gespeichert und von allen Requests im selben Environment geteilt. Damit sparst du dir den Login-Roundtrip pro Abfrage und hast quasi eine durchgehende Session.
#############
# Stolperstein
Während der Arbeiten an Bruno ( zu Hause ) bin ich über folgendes Problem gestolpert.
Nach dem holen der Session-ID kam immer ein 500er-Fehler. Das lag daran das ich
1. die ID geholt habe
2. Bruno wohl die Cookies speichert
Die Cookies kann man in Bruno über die folgenden Punkte ausschalten:
1. ![](Bruno_Cookies_1.png)
2. ![](Bruno_Cookies_2.png)
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

+160
View File
@@ -0,0 +1,160 @@
# MySQL Binary Search Fehlerhafte Zeile automatisch finden
## Hintergrund
Bei der Migration von Daten zwischen zwei Tabellen treten gelegentlich Fehler auf. Mit `LIMIT` und `OFFSET` lässt sich der fehlerhafte Bereich manuell eingrenzen dieser Prozess kann jedoch durch einen Binary-Search-Ansatz vollständig automatisiert werden.
---
## Einfaches Skript (SELECT *)
Für ein simples `SELECT *` ohne komplexe Query:
```bash
#!/bin/bash
# Konfiguration
DB_USER="root"
DB_PASS="password"
DB_NAME="datenbank"
SOURCE_TABLE="quelle"
TARGET_TABLE="ziel"
# Gesamtanzahl Zeilen ermitteln
TOTAL=$(mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -sNe \
"SELECT COUNT(*) FROM $SOURCE_TABLE;")
echo "Gesamt Zeilen: $TOTAL"
LOW=0
HIGH=$TOTAL
while [ $((HIGH - LOW)) -gt 1 ]; do
MID=$(( (LOW + HIGH) / 2 ))
FETCH=$((MID - LOW))
echo "Teste OFFSET=$LOW LIMIT=$FETCH ..."
ERROR=$(mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" 2>&1 <<EOF
INSERT INTO $TARGET_TABLE
SELECT * FROM $SOURCE_TABLE
LIMIT $FETCH OFFSET $LOW;
EOF
)
if echo "$ERROR" | grep -qi "error"; then
HIGH=$MID
echo " → Fehler gefunden, eingrenzen bis Zeile $HIGH"
else
LOW=$MID
echo " → OK, weiter ab Zeile $LOW"
fi
done
echo ""
echo "=== Fehlerhafte Zeile gefunden ==="
echo "OFFSET: $LOW"
mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e \
"SELECT * FROM $SOURCE_TABLE LIMIT 1 OFFSET $LOW;"
```
---
## Erweitertes Skript (komplexe Query mit JOINs, MAX etc.)
Wenn die Source-Query komplex ist (JOINs, Aggregatfunktionen, GROUP BY), wird sie als Variable definiert und als Subquery genutzt.
> **Wichtig:** Ein `ORDER BY` ist zwingend erforderlich, damit die Zeilenreihenfolge zwischen den Aufrufen deterministisch bleibt.
```bash
#!/bin/bash
# Konfiguration
DB_USER="root"
DB_PASS="password"
DB_NAME="datenbank"
# Deine Source-Query OHNE LIMIT/OFFSET als Subquery nutzbar
SOURCE_QUERY="SELECT a.id, MAX(b.wert), a.name
FROM quelle a
JOIN andere b ON a.id = b.ref_id
GROUP BY a.id, a.name
ORDER BY a.id"
TARGET_TABLE="ziel"
# Gesamtanzahl Zeilen der Query ermitteln
TOTAL=$(mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -sNe \
"SELECT COUNT(*) FROM ($SOURCE_QUERY) AS _count_query;")
echo "Gesamt Zeilen: $TOTAL"
LOW=0
HIGH=$TOTAL
while [ $((HIGH - LOW)) -gt 1 ]; do
MID=$(( (LOW + HIGH) / 2 ))
FETCH=$((MID - LOW))
echo "Teste OFFSET=$LOW LIMIT=$FETCH ..."
ERROR=$(mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" 2>&1 <<EOF
INSERT INTO $TARGET_TABLE
$SOURCE_QUERY
LIMIT $FETCH OFFSET $LOW;
EOF
)
if echo "$ERROR" | grep -qi "error"; then
HIGH=$MID
echo " → Fehler, eingrenzen bis Zeile $HIGH"
else
LOW=$MID
echo " → OK, weiter ab Zeile $LOW"
fi
done
echo ""
echo "=== Fehlerhafte Zeile ==="
mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e \
"$SOURCE_QUERY LIMIT 1 OFFSET $LOW;"
```
---
## Gezielten Wert aus der fehlerhaften Zeile ausgeben
### Variante 1 Subquery-Wrapping
```bash
echo "=== Fehlerhafte Zeile ==="
mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e \
"SELECT a.id, a.name FROM ($SOURCE_QUERY) AS _fehler LIMIT 1 OFFSET $LOW;"
```
### Variante 2 Direkte Query (empfohlen bei Aggregaten)
```bash
echo "=== Fehlerhafte Zeile Detailansicht ==="
mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e \
"SELECT
a.id AS 'ID',
a.name AS 'Name',
MAX(b.wert) AS 'Max-Wert'
FROM quelle a
JOIN andere b ON a.id = b.ref_id
GROUP BY a.id, a.name
ORDER BY a.id
LIMIT 1 OFFSET $LOW;"
```
Variante 2 ist bei `MAX()` und anderen Aggregatfunktionen übersichtlicher, da die Rohwerte direkt aus der Query kommen und nicht erst durch ein Subquery-Wrapping gehen.
---
## Hinweise
- **ORDER BY** ist Pflicht für deterministische Ergebnisse bei wiederholten Aufrufen.
- Die erfolgreichen INSERT-Blöcke bleiben in der Zieltabelle erhalten bei Bedarf kann jeder Block in eine Transaktion mit `ROLLBACK` bei Fehler gekapselt werden.
- Der Binary Search reduziert die Anzahl der Testläufe auf `log₂(n)` bei 1000 Zeilen also maximal 10 Schritte.
+161
View File
@@ -0,0 +1,161 @@
# PHP & CSS Tabellen und Formulare
## 1. Input-Feld mit vorausgefülltem Wert
**Problem:** `$value=` ist kein gültiges HTML-Attribut.
**Lösung:**
```html
<input name="ls" value="<?= htmlspecialchars($row['ls']) ?>">
```
Doppelte Anführungszeichen außen verwenden, damit die einfachen Anführungszeichen im PHP-Array (`$row['ls']`) nicht kollidieren.
Weiterer Fehler im Original: doppeltes `</td></td>` und fehlendes schließendes `</td>`.
**Korrekter Block:**
```html
<form method="post">
<table>
<tr>
<th>Ticket-Nr.</th>
<td><?= htmlspecialchars($row['tt']) ?></td>
</tr>
<tr>
<th>Auftraggeber</th>
<td><input name="ls" value="<?= htmlspecialchars($row['ls']) ?>"></td>
<th>Bearbeiter</th>
<td><?= htmlspecialchars($row['bearbeiter']) ?></td>
</tr>
</table>
</form>
```
---
## 2. Spaltenbreite in Tabellen
### Option 1 Inline Style
```html
<th style="width: 150px;">Auftraggeber</th>
```
### Option 2 CSS-Klasse
```css
table th { width: 150px; }
table th:first-child { width: 100px; }
```
### Option 3 `<col>`-Element (zentral für jede Spalte)
```html
<table>
<colgroup>
<col style="width: 150px;">
<col style="width: 250px;">
<col style="width: 150px;">
<col style="width: 250px;">
</colgroup>
...
</table>
```
> **Wichtig:** `table-layout: fixed` ist erforderlich, damit die Breiten zuverlässig greifen.
```css
table {
table-layout: fixed;
width: 100%;
}
```
---
## 3. Spaltenbreiten zentral für mehrere Tabellen
Jeder Tabelle eine eigene Klasse geben:
```html
<table class="tabelle-ticket">
<table class="tabelle-adressen">
```
CSS in einer zentralen `.css`-Datei:
```css
table {
table-layout: fixed;
width: 100%;
}
.tabelle-ticket col:nth-child(1) { width: 150px; }
.tabelle-ticket col:nth-child(2) { width: 250px; }
.tabelle-ticket col:nth-child(3) { width: 150px; }
.tabelle-ticket col:nth-child(4) { width: 250px; }
.tabelle-adressen col:nth-child(1) { width: 100px; }
.tabelle-adressen col:nth-child(2) { width: 300px; }
```
Einbinden per:
```html
<link rel="stylesheet" href="style.css">
```
---
## 4. Tabelle ignoriert Spaltenbreiten (Auto-Breite)
**Ursache:** Fehlendes `table-layout: fixed`.
```css
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed; /* ← das fehlte */
}
```
Außerdem: `max-width: auto` ist ungültig. Entweder weglassen oder konkreten Wert setzen:
```css
.content {
max-width: 1200px; /* oder weglassen */
}
```
---
## 5. Input-Breite sprengt Tabellenlayout
**Ursache:** `input { width: 100%; }` greift auch auf Inputs in Tabellenzellen.
**Lösung:** Inputs in Tabellen explizit ausschließen:
```css
/* Inputs nur im Formular-Bereich */
.form-bereich input,
.form-bereich select {
width: 100%;
padding: 8px;
margin-top: 4px;
}
/* Inputs in Tabellen zurücksetzen */
td input, td select {
width: auto;
padding: 2px 4px;
margin-top: 0;
}
```
Oder Formular-Bereich per Klasse kapseln:
```html
<div class="form-bereich">
<label>...</label>
<input ...>
</div>
<table>
... <!-- inputs hier bleiben unberührt -->
</table>
```