我在这里得到了一些关于交换同一表行中的某些数据的帮助。
不幸的是,我无法在实践中应用这些解决方案,因为我代表的问题太弱了,因此使用提供的解决方案我无法获得预期的结果。
为此,我改进了示例并使其非常易于使用,同时更可能尝试我的具体情况,希望这篇文章不会被视为重复或冒犯。
创建表:
DROP TABLE IF EXISTS kalksad1;
CREATE TABLE kalksad1(
kalk_id int PRIMARY KEY,
brkalk integer,
brred integer,
description text
);
INSERT INTO kalksad1 VALUES
(12, 2, 5, 'text index 12 doc 2 row 5'),
(26, 2, 1, 'text index 26 doc 2 row 1'),
(30, 2, 2, 'text index 30 doc 2 row 2'),
(32, 4, 1, 'text index 32 doc 4 row 1'),
(36, 1, 1, 'text index 36 doc 1 row 1'),
(37, 1, 2, 'text index 37 doc 1 row 2'),
(38, 5, 1, 'text index 38 doc 5 row 1'),
(39, 5, 2, 'text index 39 doc 5 row 2'),
(42, 2, 3, 'text index 42 doc 2 row 3'),
(43, 2, 4, 'text index 43 doc 2 row 4'),
(46, 3, 1, 'text index 46 doc 3 row 1'),
(47, 3, 2, 'text index 47 doc 3 row 2');
需要什么?
进行查询,该查询仅在同一“brkalk”的“brred”列中交换数字。
'brred' 和 'brkalk' 都是通过程序在外部定义的。
例如,我们将采用 brkalk=2,brred=3。
这意味着我们应该只在 brkalk=2 的行中交换 brred 值。
这里有两个提供的解决方案,可以作为参考。
如果它们可行,这两种解决方案都会很有用。
第一个是因为它可以交换行而不管顺序和距离如何,第二个是因为它只与最常见的需要交换的第一行上下交换。第二种解决方案的问题是我不知道它交换了什么,而是交换第一行和最后一行而不是第 3 行和第 2 行。
应该修复。
第一个查询在新情况下根本不起作用,所以我想知道是否有人可以修复它。无论外部参数的“方向”如何,它都可以用于交换行,例如交换第 4 行和第 1 行。
澄清一下,当我说“交换行”时,我的意思是只交换属于同一“brkalk”的“brred”列中的值(在本例中为 2)。
第一个查询:
UPDATE kalksad1 dst
SET brred=src.brred
FROM kalksad1 src
WHERE src.brkalk='2'
AND dst.kalk_id IN(2,3)
AND src.kalk_id IN(2,3)
AND dst.kalk_id <> src.kalk_id;
第二次查询
WITH cte1 AS (
SELECT row_number() OVER(ORDER BY kalk_id ASC) AS row_num, kalk_id, brred
FROM kalksad1
WHERE kalk_id >= 3 ORDER BY kalk_id LIMIT 2
)
UPDATE kalksad1 AS t
SET brred = COALESCE(c2.brred, t.brred)
FROM cte1 AS c1
LEFT OUTER JOIN cte1 AS c2 ON c2.row_num <> c1.row_num
WHERE t.kalk_id = c1.kalk_id AND brkalk='2';
要查看数据,最好使用:
SELECT * FROM kalksad1 WHERE brkalk='2' ORDER BY brred;
我希望有人根据所描述的需求修复上层查询以使其变得可行,或者提供可用于这种交换的新解决方案。
所以,多亏了 Roman 和 wildplasser,我得到了这个……
Private Function swap_row(ByVal doc_num As Integer, ByVal src_row As Integer, ByVal dest_row As Integer) As Integer
Dim affected As Integer = 0
Dim conn As NpgsqlConnection = getConnection()
Dim t As NpgsqlTransaction = conn.BeginTransaction()
Using cmd As New NpgsqlCommand( _
"UPDATE " & myKalkSadTable & " AS dst SET brred = src.brred " & _
"FROM " & myKalkSadTable & " AS src " & _
"WHERE(src.brkalk = " & doc_num.ToString & ") " & _
"AND dst.brkalk = " & doc_num.ToString & " " & _
"AND dst.brred IN (" & src_row.ToString & "," & dest_row.ToString & ") " & _
"AND src.brred IN (" & src_row.ToString & "," & dest_row.ToString & ") " & _
"AND src.kalk_id <> dst.kalk_id", conn)
affected = CInt(cmd.ExecuteNonQuery())
cmd.Dispose()
End Using
If affected = 2 then t.Commit()
t.Dispose()
conn.Close()
conn.Dispose()
Return affected
End Function
Private Sub DataGridView2_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView2.KeyDown
If e.Control And e.KeyCode = Keys.Left Then
swap_row(kalkbr, selected_row, selected_row - 1)
Refreshlist(kalkbr)
End If
If e.Control And e.KeyCode = Keys.Right Then
swap_row(kalkbr, selected_row, selected_row + 1)
Refreshlist(kalkbr)
End If
...ETC ...