基于多个“ WHERE IN”条件的更新

时间:2019-09-03 22:15:53

标签: sql sql-server

假设我有一个要根据多种条件进行更新的表。这些条件中的每一个都是大小相等的数组,唯一有效的情况是匹配数组中相同索引的情况。

也就是说,如果我们使用以下SQL子句

pipeline {
    agent('linux2') { 
        docker {
            label '<slave-label-here>'
            image '<image-name>:<image-tag>'
            registryUrl 'https://<server>:<port>'
            registryCredentialsId '<jenkins-credentials-for-docker-login>'
            args '-v maven-repo:/usr/share/maven/ref/repository/'
        }
    }

    parameters {
        booleanParam(name: 'SONAR', defaultValue: false, description: 'Select this option to run SONAR Analysis')
    }

    stages {
        stage('Build') {
            steps {
                sh 'mvn clean install -s /usr/share/maven/ref/settings.xml -f pom.xml'
            }
        }
    }
}
对于具有UPDATE Foo SET bar = 1 WHERE a IN ( 1, 2, 3, 4, 5) AND b IN ( 6, 7, 8, 9, 0) AND c IN ('a', 'b', 'c', 'd', 'e') 的任何行,

bar都将设置为1。

不是 我想要的。

我需要一个只有a = 1, b = 8, c = 'e'a = 1, b = 6, c = 'a'(等等)起作用的子句。

很明显,我可以将子句重写为

a = 2, b = 7, c = 'b'

这行得通,但是很难扩展。鉴于条件的值是可变的并且可以通过编程获得,因此如果我可以将每个数组都放在一个位置而不用构建字符串构建循环来正确调用WHERE,那会更好。

那么,是否有更好,更优雅的方式来使行为与最后一个块相同?

5 个答案:

答案 0 :(得分:3)

使用表值构造函数:

UPDATE f 
SET bar = 1
WHERE EXISTS (
   SELECT * FROM (VALUES (1,6,'a'),(2,7,'b'),(3,8,'c')) AS Trios(a,b,c)
   WHERE Trios.a = f.a AND Trios.b = f.b AND Trios.c = f.c
)

答案 1 :(得分:1)

您可以使用values()join

UPDATE f
    SET bar = 1
    FROM Foo f JOIN
         (VALUES (1, 6, 'a'),
                 (2, 7, 'b'),
                 . . .
         ) v(a, b, c)
         ON f.a = v.a AND f.b = v.b AND f.c = v.c;

答案 2 :(得分:0)

尝试一下可能会起作用

DECLARE @Temp AS Table ( a int, b int, c varchar(50))

INSERT INTO @Temp(a,b,c)
VALUES(1, 6, 'a'),
(2, 7, 'b'),
(3, 8, 'c'),
(4, 9, 'd'),
(5, 0, 'e')


UPDATE F
SET bar = 1
FROM FOO F INNER JOIN @Temp T 
ON F.a = T.a AND  F.b = T.b AND  F.c = T.c

答案 3 :(得分:0)

读取数据时,请勿将其另存为单个字符串,然后使用以下内容:

update foo
set bar = 1
where concat(a,b,c) in ('16a','27b','38c','49d','50e')

这可能不是最优雅的方法,但它非常实用且简单。

答案 4 :(得分:0)

我在这里可能完全不合时宜-我不确定您是否要传递一组值或您拥有什么-但我的第一个想法是使用一系列CTE。

我对您的数据做出了相当大的假设,但这是一个示例,您可以根据自己对问题的看法在SSMS中运行。

-- Create @Data and insert some, er... data ---
DECLARE @Data TABLE ( id INT IDENTITY(100,1) PRIMARY KEY, a VARCHAR(1), b VARCHAR(1), c VARCHAR(1) );

INSERT INTO @Data ( a ) VALUES ('1'), ('2'), ('3'), ('4'), ('5');
INSERT INTO @Data ( b ) VALUES ('6'), ('7'), ('8'), ('9'), ('0');
INSERT INTO @Data ( c ) VALUES ('a'), ('b'), ('c'), ('d'), ('e');

因此,我们假设这是您的数据。我将其简化以使其易于理解。

+-----+---+---+---+
| id  | a | b | c |
+-----+---+---+---+
| 100 | 1 |   |   |
| 101 | 2 |   |   |
| 102 | 3 |   |   |
| 103 | 4 |   |   |
| 104 | 5 |   |   |
| 105 |   | 6 |   |
| 106 |   | 7 |   |
| 107 |   | 8 |   |
| 108 |   | 9 |   |
| 109 |   | 0 |   |
| 110 |   |   | a |
| 111 |   |   | b |
| 112 |   |   | c |
| 113 |   |   | d |
| 114 |   |   | e |
+-----+---+---+---+

使用对齐的“数组”索引查询数据:

;WITH CTE_A AS (
    SELECT
        id,
        ROW_NUMBER() OVER ( ORDER BY id ) AS a_row_id,
        a
    FROM @Data WHERE a IS NOT NULL
)
, CTE_B AS (
    SELECT
        id,
        ROW_NUMBER() OVER ( ORDER BY id ) AS b_row_id,
        b
    FROM @Data WHERE b IS NOT NULL
)
, CTE_C AS (
    SELECT
        id,
        ROW_NUMBER() OVER ( ORDER BY id ) AS c_row_id,
        c
    FROM @Data WHERE c IS NOT NULL
)
SELECT 
    CTE_A.id, CTE_A.a_row_id, CTE_A.a
    , CTE_B.id, CTE_B.b_row_id, CTE_B.b
    , CTE_C.id, CTE_C.c_row_id, CTE_C.c
FROM CTE_A
JOIN CTE_B ON CTE_A.a_row_id = CTE_B.b_row_id
JOIN CTE_C ON CTE_A.a_row_id = CTE_C.c_row_id;

哪个返回:

+-----+----------+---+-----+----------+---+-----+----------+---+
| id  | a_row_id | a | id  | b_row_id | b | id  | c_row_id | c |
+-----+----------+---+-----+----------+---+-----+----------+---+
| 100 |        1 | 1 | 105 |        1 | 6 | 110 |        1 | a |
| 101 |        2 | 2 | 106 |        2 | 7 | 111 |        2 | b |
| 102 |        3 | 3 | 107 |        3 | 8 | 112 |        3 | c |
| 103 |        4 | 4 | 108 |        4 | 9 | 113 |        4 | d |
| 104 |        5 | 5 | 109 |        5 | 0 | 114 |        5 | e |
+-----+----------+---+-----+----------+---+-----+----------+---+

同样,对数据进行假设(特别是存在一个可以排序的ID),但这基本上是通过将a,b和c值链接到它们的相对“索引”(ROW_NUMBER)来进行旋转的。通过以这种方式使用ROW_NUMBER,我们可以创建一个临时数组索引值(a_row_id,b_row_id,c_row_id),该值可用于连接结果值。

可以轻松地将此示例更改为UPDATE语句。

这是否解决了您的问题?