MySQL - Wert aus vorheriger Zeile übernehmen und einfügen

Max-Berater

Erfahrenes Mitglied
1644510318155.png

Ich möchte gerne die Rechnungsnummer RE90392022die in beiden Zeilen vorhanden in die dritte Zeile (leer) einfügen, wenn in Zeile x Wert y vorhanden ist. Wie sage ich dem System, dass er den Wert der vorherigen Zeile nehmen soll?
 

Yaslaw

alter Rempler
Moderator
Grundsätzlich gibt es in einer DB nicht "Die Zeile davor". Das ist je nach Sortierung und Filterung unterschiedlich. Die Daten siond auch nicht wie in einem Excel in einer festen Reihenfolge gespeichert.

In einem SQL, kannst du aber auf einen Wert der Ausgabezeile davor zugreifen. In MySQL ist @varname:=value die formel. Zudem werden die Ausgabefelder in der angegeben Reihenfolge abgearbeitet. Sprich, du kannst in Spalte 3 auf die Spalten 1 und 2 zugreifen.
SQL:
select
    t.my_value,
    -- Variable ausgeben
    @prev_value as prev_value,
    -- und danach die Variable neu setzen
    @prev_value := t.my_value as save_for_next_row
from my_table t
order by t.my_sort_field
und wenn du die hilfsspalte nicht sehen willst.
SQL:
select my_value, prev_value
from (
    select
        t.my_value,
        @prev_value as prev_value,
        @prev_value := t.my_value as save_for_next_row
    from my_table t
    order by t.my_sort_field
)
 
Zuletzt bearbeitet:

Zvoni

Erfahrenes Mitglied
Grundsätzlich gibt es in einer DB nicht "Die Zeile davor". Das ist je nach Sortierung und Filterung unterschiedlich. Die Daten siond auch nicht wie in einem Excel in einer festen Reihenfolge gespeichert.
Doch, gibt es.
Nennt sich LAG-Funktion
MySQL LAG() Function Explained By Practical Examples
und für "Die Zeile danach" gibt es die LEAD-Funktion
Wobei besssere Bezeichnungen
"Wenn in Zeile Darunter der Wert aus Zeile Darüber gezeigt werden soll" (LAG-Funktion)
"Wenn in Zeile Darüber der Wert aus Zeile Darunter gezeigt werden soll" (LEAD-Funktion)
sind

Ungetestet müsste es irgendwie so gehen:
SQL:
SELECT
EinFeld,
COALESCE(RENummer,LAG(RENummer),'Nix gefunden') AS MeineRechnung
FROM
IrgendeineTabelle
ORDER BY
EinFeld,
RENummer

EDIT: Habs mal in SQLite getestet
Das war meine Datenbasis
IDDescription
1Job1
2Job2
3Job3
4Job4
5
6Job6
7Job7
8
9Job9

SQL:
SELECT
ID,
coalesce(Description, LAG(Description) OVER(ORDER BY ID),'Sorry') AS Description
FROM Jobs ORDER BY ID
Ergebnis:
1Job1
2Job2
3Job3
4Job4
5Job4
6Job6
7Job7
8Job7
9Job9


Das Einfügen (UPDATE) ist dann ein simples UPDATE-Statement gejoint auf o.g. SELECT, mit Prüfung auf IS NULL im Original-Satz.

Ungetestet
SQL:
UPDATE Jobs As J1
SET J1.Description=S1.Vorher
FROM
(SELECT ID,coalesce(Description, LAG(Description) OVER(ORDER BY ID),'Sorry') As Vorher FROM Jobs ORDER BY ID) As S1
WHERE
J1.ID=S1.ID AND J1.Description IS NULL
 
Zuletzt bearbeitet:

Zvoni

Erfahrenes Mitglied
Wieder was dazugelernt.
Aber dass es keine fixe Reihenfolge gibt, das stimmt. Darum muss man im LAG ja den ORDER BY mitgeben, damit die Methode den vorherigen Datensatz ermitteln kann.

Hier habe ich eine nette ANleitung für LAG in MySQL gefunden: MySQL LAG() Function Explained By Practical Examples
Faustregel: Der Order By innerhalb der LAG-Funktion ist derselbe wie der ORDER BY des zugrundeliegenden Selects (kann ja eingebettet sein)

Dir ist klar, dass dein Link derselbe wie meiner oben ist? :)

EDIT: Das funktioniert natürlich nur, wenn echte "NULL"'s in den Feldern stehen, sonst greift COALESCE ins Leere. Ansonten vielleicht mit CASE WHEN Trim(Description)='' THEN blabablbabla.
Müsste ich aber testen
 

Max-Berater

Erfahrenes Mitglied
Danke für Eure ausführlichen Anleitungen. Ich hab gestern mal gebastelt aber ohne pos. Resultat.

In Belegfeld 1 Reihe 3 soll die Rechnungsnummer RE91502022 rein, damit wir wissen, dass dieses zusammen gehört.

1645026757251.png
 

Max-Berater

Erfahrenes Mitglied
SQL:
select my_value, prev_value
from (
    select
        t.`Belegfeld 1`,
        @prev_value as prev_value,
        @prev_value := t.`Beleginfo 1` as save_for_next_row
    from RECHNUNGEN
    order by t.`Belegfeld 2`
 
Zuletzt bearbeitet von einem Moderator:

Yaslaw

alter Rempler
Moderator
Wenn man Beispiele übernimmt, sollte man versuchen sie zu verstehen und dann an die eigenen Gegebenheiten anzupassen. Dann sollte man die Fehlermeldungen anschaen. Ich bin sicher, dieses SQL Statement wirft ein Fehler, da das Feld my_value nicht bekannt ist.
Aber ich würde diese Variante eh verwerfen und auf LAG setzen, dass genau dazu da ist.

Beipieldaten der Tabelle t_2124206
Code:
BELEGFELD_1 | BELEGFELD_2 | BUCHUNGTEXT
RE1234      | B1          | TEST
RE1234      | B1          | TEST 2
            | B1          | TEST 3
RE456       | B2          |
            | B2          |

SQL
SQL:
SELECT
    IFNULL(
        t.BELEGFELD_1, 
        LAG(t.BELEGFELD_1, 1) 
            over (
                -- Gruppieren über BELEGFELD_2
                PARTITION BY t.BELEGFELD_2    
                -- Absteigend sortiert BELEGFELD_1
                ORDER BY t.BELEGFELD_1 DESC
            )
    ) AS NEW_BELEGFELD_1,
    t.*
FROM t_2124206 t

Resultat
Code:
NEW_BELEGFELD_1 | BELEGFELD_1 | BELEGFELD_2 | BUCHUNGTEXT
RE1234          | RE1234      | B1          | TEST 2
RE1234          | RE1234      | B1          | TEST
RE1234          |             | B1          | TEST 3
RE456           | RE456       | B2          |
RE456           |             | B2          |