PostgreSQL, Swap data de cierta columna en dos filas
Tengo una función compleja para intercambiar datos de la misma columna de nombre en diferentes filas. Leo los datos de la primera, los almaceno en variables temporales locales, leo los datos de la segunda fila y, si se cumplen ciertas condiciones (mín / máx), la guardo en la primera fila y luego las variables temporales en la segunda fila, lo que es una operación lenta y propensa a errores .
Así que pensé que tal vez el mismo resultado podría lograrse solo con SQL.
Aquí hay datos de muestra:
CREATE TEMP TABLE tbl(
id int PRIMARY KEY,
doc_num integer,
doc_text text
);
INSERT INTO tbl VALUES
(1, 1, 'First column text1'),
(2, 2, 'First column text2'),
(4, 3, 'First column text3'),
(7, 4, 'First column text4');
Piont es intercambiar solo los datos de la columna 'doc_num' en la dirección deseada, que puede ser para subir o bajar lo que hago con funciones separadas.
Si puedo escribir una consulta simple en inglés que sonará así:
Primera consulta:
SWAP DOC_NUM in row 2 with DOC_NUM in row 3 IF DOC_NUM in row 3 IS <= MAX(DOC_NUM);
Segunda consulta:
SWAP DOC_NUM in row 3 with DOC_NUM in row 2 IF DOC_NUM in row 2 IS >= MIN(DOC_NUM);
¿Es posible escribir esas consultas con PostgreSQL y cómo?
Aquí está el código real (que es feo) de un programa real que "hace un trabajo" y necesita mejoras.
Private Sub DataGridView2_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView2.KeyDown
'SWAP --------------------------------------
If e.Control And e.KeyCode = Keys.Left Then
Debug.Print("Swap left/down")
Dim target_nrow As Integer
Dim target_index As Integer
Dim selected_nrow As Integer
Dim selected_index As Integer
Dim target_row As Integer = selected_row - 1
Using conn As New NpgsqlConnection(String.Format("Server={0};Port={1};User Id={2};Password={3};Database={4};", dbServer, dbPort, dbUser, dbPass, mydatabase))
conn.Open()
Dim t As NpgsqlTransaction = conn.BeginTransaction()
Using cmd As New NpgsqlCommand( _
"SELECT cur_id, doc_num, nrow " & _
"FROM " & mytable & " " & _
"WHERE doc_num='" & active_doc.ToString & "' AND nrow='" & selected_row.ToString & "'", conn)
Using dr As NpgsqlDataReader = cmd.ExecuteReader()
While dr.Read()
selected_index = CInt(dr(0))
selected_nrow = CInt(dr(2))
End While
End Using
End Using
Using cmd As New NpgsqlCommand( _
"SELECT cur_id, doc_num, nrow " & _
"FROM " & mytable & " " & _
"WHERE doc_num='" & active_doc.ToString & "' AND nrow='" & target_row.ToString & "'", conn)
Using dr As NpgsqlDataReader = cmd.ExecuteReader()
While dr.Read()
target_index = CInt(dr(0))
target_nrow = CInt(dr(2))
End While
End Using
End Using
Dim updated_t As Integer = 0
Using cmd As New NpgsqlCommand( _
"UPDATE " & mytable & " SET " & _
"nrow=" & selected_nrow & " " & _
"WHERE cur_id=" & target_index.ToString, conn)
updated_t = CInt(cmd.ExecuteNonQuery())
cmd.Dispose()
End Using
Dim updated_s As Integer = 0
Using cmd As New NpgsqlCommand( _
"UPDATE " & mytable & " SET " & _
"nrow=" & target_nrow & " " & _
"WHERE cur_id=" & selected_index.ToString, conn)
updated_s = CInt(cmd.ExecuteNonQuery())
cmd.Dispose()
End Using
If updated_s > 0 And updated_t > 0 Then
t.Commit()
Else
t.Rollback()
End If
t.Dispose()
conn.Close()
conn.Dispose()
End Using
Refreshlist(active_doc)
End If
If e.Control And e.KeyCode = Keys.Right Then
Debug.Print("Swap right/up")
'similar code to swap up again
End If
Se cuestiona toda la historia sobre cómo hacer esto más corto, más rápido y más elegante.