0

我在这里得到了一些关于交换同一表行中的某些数据的帮助。
不幸的是,我无法在实践中应用这些解决方案,因为我代表的问题太弱了,因此使用提供的解决方案我无法获得预期的结果。
为此,我改进了示例并使其非常易于使用,同时更可能尝试我的具体情况,希望这篇文章不会被视为重复或冒犯。

创建表:

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 ...

4

1 回答 1

1

对于第一个,您必须在 dst 和 src 上过滤 brkalk:

update kalksad1 as dst set
    brred = src.brred 
from kalksad1 as src 
where
    src.brkalk = 2 and dst.brkalk = 2 and
    dst.brred in (2,3) and
    src.brred in (2,3) and
    src.kalk_id <> dst.kalk_id;

sql 小提琴演示

我认为第二个太复杂了,当我认为你想用确切的 ID 交换行和下一个时,我创建了它

于 2013-08-15T10:44:27.483 回答