简体   繁体   English

T-SQL:我可以使用另一个表中的行来更新表吗?

[英]T-SQL: Can I update a table using rows from another table?

I have a table that looks like this 我有一张看起来像这样的桌子

[UniqueID]-[1]-[2]-[3]-[etc... to 250
------------------------------
00000A    | 0 | 0 | 1 |
00000B    | 0 | 1 | 0 |
00000C    | 0 | 1 | 1 |

I pivoted that table from another table with two columns, the unique ID and the number (1, 2, 3, etc.) 我从另一个具有两列(唯一ID和数字(1、2、3等)的表)中透视该表。

I have another table which has two columns, a number and an elimination. 我有另一个表,该表有两列,一个数字和一个消除。 For example, if the number is 2 and the elimination is 3, I would take the unique ID 00000C, go to column 3, and change the 1 to a 0. 例如,如果数字为2且消除为3,我将采用唯一ID ID 00000C,转到第3列,并将1更改为0。

In the past, I have manually written: 过去,我手动编写了以下内容:

UPDATE [TABLE] SET [3] = 0 WHERE [2] = 1

I need to do this about 150 times, so it would be much more concise to write a query to read from the second table to modify the first. 我需要执行约150次,因此编写查询以从第二个表读取以修改第一个表会更加简洁。 Additionally, when I have to make changes, I will only need to modify the table instead of making changes to the query itself. 另外,当我必须进行更改时,只需要修改表即可,而无需更改查询本身。

I know I can probably do this by pivoting the second table and using Dynamic SQL, and I will do that if I have to, but I'm wondering if any of you have some other ideas to solve this problem. 我知道我可以通过旋转第二张表并使用Dynamic SQL来做到这一点,如果需要的话,我会这样做,但是我想知道是否还有其他想法可以解决此问题。

Basically, what I am looking to do is this: 基本上,我要做的是:

UPDATE [TABLE] SET [(SELECT elim FROM ElimTbl)] = 0 
WHERE [(SELECT num FROM ElimTbl)] = 1

I know that's invalid, but I'm hoping someone has a better idea. 我知道那是无效的,但我希望有人有更好的主意。

Thank you for your time! 感谢您的时间!

Target table is not normalized because [1], [2], ..., [150] are nothing more than a repeating group of columns ( 1 , 2 ). 目标表不是归一化,因为[1], [2], ..., [150]是无非重复组列的多个( 12 )。 This means that target table breaks first normal form. 这意味着目标表将打破第一个范式。 This problem generates another problem: UPDATE statement should include the same expression with small modifications (a [sub]query that finds elimination ) 150th times. 这个问题产生了另一个问题: UPDATE语句应该包含相同的表达式,但该表达式需要进行150次细微的修改(找到消除的[sub]查询)。

Instead, I would use a normalized target table and when is needed, data from target table can be easily pivoted using PIVOT operator: 相反,我将使用规范化的目标表,并且在需要时,可以使用PIVOT运算符轻松地旋转目标表中的数据:

/*
[UniqueID]-[1]-[2]-[3]-etc... 150
------------------------------
00000A    | 0 | 0 | 1 |
00000B    | 0 | 1 | 0 |
00000C    | 0 | 1 | 1 |
*/

DECLARE @Target TABLE (
    UniqueID    VARCHAR(6) NOT NULL,
    Num         INT NOT NULL,   
        PRIMARY KEY (UniqueID, Num),
    Value       BIT NOT NULL
);
INSERT  @Target 
VALUES  
('00000A', 3, 1),
('00000B', 2, 1),
('00000C', 2, 1), ('00000C', 3, 1);

DECLARE @Source TABLE (
    UniqueID    VARCHAR(6) NOT NULL,
        PRIMARY KEY (UniqueID),
    Num         INT NOT NULL
);
INSERT  @Source 
VALUES  
('00000B', 3), 
('00000C', 2);

SELECT * FROM @Target
SELECT * FROM @Source

-- Intermediate query -中级查询

SELECT  s.*, x.*
FROM    @Source s
OUTER APPLY (
    SELECT  TOP(1) *
    FROM    @Target t
    WHERE   t.Num = s.Num
    AND     t.Value = 1
    AND     t.UniqueID >= s.UniqueID
    ORDER BY t.UniqueID 
) x
/*
Results
UniqueID Num UniqueID Num Value
-------- --- -------- --- -----
00000B   3   00000C   3   1
00000C   2   00000C   2   1
*/

-- Final query -最终查询

UPDATE  t           --| or DELETE t 
SET     Value = 0   --| 
FROM    @Target AS t
WHERE   EXISTS (
    SELECT  *
    FROM    @Source s
    CROSS APPLY (
        SELECT  TOP(1) *
        FROM    @Target t
        WHERE   t.Num = s.Num
        AND     t.Value = 1
        AND     t.UniqueID >= s.UniqueID
        ORDER BY t.UniqueID 
    ) x
    WHERE x.UniqueID = t.UniqueID
)

SELECT * FROM @Target
/*
Results:
UniqueID Num         Value
-------- ----------- -----
00000A   3           1
00000B   2           1
00000C   2           0
00000C   3           0
*/

-- Pivot -枢轴

;WITH CteSource 
AS 
(SELECT UniqueID, Num, CONVERT(TINYINT, Value) AS ValueAsInt FROM @Target)
SELECT  pvt.*
FROM    CteSource s
PIVOT( MAX(s.ValueAsInt) FOR s.Num IN ([1], [2], [3], /*...*/ [150]) ) pvt
/*
UniqueID 1    2    3    150
-------- ---- ---- ---- ----
00000A   NULL NULL 1    NULL --> NULLs can be replaced with 0 with ISNULL / COALESCE
00000B   NULL 1    NULL NULL
00000C   NULL 0    0    NULL
*/
Update t1
Set t1.value = t2.value
FROM
t1
INNER JOIN t2 ON t1.KEY = t2.KEY

After taking some time, I found an answer that works even better and is simpler. 花了一些时间后,我发现了一个更好,更简单的答案。

My original table looks like this: 我的原始表格如下所示:

[Table A]
ID | Num
--------
A  | 3
B  | 2
C  | 2
C  | 3

My other table is: 我的另一个表是:

Num | Eliminate
---------------
2   | 3

Basically that means that if any given ID is assigned both the number 2 and 3, 3 should be eliminated while leaving 2. If I join these tables, I get this: 基本上,这意味着如果给定给定的ID,则数字2和3都应在离开2时被消除3。如果我加入这些表,则会得到:

ID | Num | Eliminate
--------------------
A  | 3   | NULL
B  | 2   | 3
C  | 2   | 3
C  | 3   | NULL

I can then produce a table with ID and Eliminate (without nulls): 然后,我可以生成一个具有ID和Eliminate(无null)的表:

[Table B]
ID | Eliminate
---------------
B  | 3
C  | 3

Finally, I can produce an output using the following: 最后,我可以使用以下命令产生输出:

SELECT [ID], [Num] FROM [Table A]
EXCEPT
SELECT [ID], [Eliminate] FROM [Table B]

This produces the output: 产生输出:

ID | Num
--------
A  | 3
B  | 2
C  | 2

Which is what I'm looking for, now I can pivot it if I would like or perform any other operations. 这就是我要寻找的,现在,如果需要或可以执行任何其他操作,可以将其旋转。 This solution was much simpler than I thought, but I just didn't see it until a colleague suggested it... Hopefully this can help someone else stuck in the same situation! 这个解决方案比我想象的要简单得多,但是直到同事提出来之后我才看到它……希望这可以帮助陷入困境的其他人!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 T-SQL:将列转换为行并插入/更新另一个表 - T-SQL: convert columns to rows and insert/update another table 使用T-Sql,如何从远程服务器上的一个表插入本地服务器上的另一个表? - Using T-Sql, how can I insert from one table on a remote server into another table on my local server? T-SQL:使用“来自变量”查询更新临时表 - T-SQL: Update temp table using “from variable” query 根据另一个表数量显示行&lt;= SQL(T-SQL) - Show rows <= according to another table quantity SQL (T-SQL) 更新表/ T-SQL - Update Table/T-SQL SQL:如何使用 group by 从表中选择不在另一个表中的行? - SQL: How can I select rows from a table that aren't in another one using group by? 当 SQL 服务器中另一个表的两个值之间时,T-SQL 使用 case 语句更新列 - T-SQL update column with case statement when between two values from another table in SQL Server 使用 T-SQL 根据先前行的值逐行更新表 - Using T-SQL to update a table row by row based on previous rows value 如何使用t-sql用来自table2的记录更新table1 - how to update table1 with records from table2 using t-sql T-SQL:从一个表中选择外键,然后在另一个表中找到对应的行 - T-SQL: Select foreign key from one table and find corresponding rows in another
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM