Sql server Transact-sql:删除表中的一个对应行
我们有一个类似的表格: 时间戳、计数、bunchOData 计数始终为1,除非有人出错并希望删除条目。删除在表中显示为新的、相同的行,计数为-1。因此:Sql server Transact-sql:删除表中的一个对应行,sql-server,tsql,Sql Server,Tsql,我们有一个类似的表格: 时间戳、计数、bunchOData 计数始终为1,除非有人出错并希望删除条目。删除在表中显示为新的、相同的行,计数为-1。因此: timestamp count bunchOData ------------------- ----- ---------- 2017-05-31 13:42:16 1 stuff 2017-05-31 13:42:27 -1 stuff 我必须将数据移动到一个新表中,在该表中删除的数据将被
timestamp count bunchOData
------------------- ----- ----------
2017-05-31 13:42:16 1 stuff
2017-05-31 13:42:27 -1 stuff
我必须将数据移动到一个新表中,在该表中删除的数据将被简单地删除。
因此,要迁移数据,我必须:
对于计数为-1的每块板,删除它和具有相同bunchOData且计数为1的最近(按时间)单板
我如何有效地做到这一点
编辑:为了让事情更清楚一些:
下面是表格中的示例:
DATE_TIME SPECIE_CODE LOAD LOAD_LIMIT THICKNESS GRADE_CODE SURFACE_MEASURE FBM LOG_COUNT
--------------------------- ----------- -------------------- -------------------- ---------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -----------
2016-12-01 10:40:46 ASH 850-OHP 15000 4/4 Sel 13 13 1
2016-12-01 10:40:52 ASH 850-OHP 15000 4/4 Sel -13 -13 -1
2016-12-01 10:48:32 ASH 850-OHP 15000 4/4 Sel 6 6 1
2016-12-01 10:48:43 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:48:51 ASH 850-BSI1 10000000 4/4 Sel S 5 5 1
2016-12-01 10:48:59 ASH 850-EMPIRE 500 4/4 2&3Com 6 6 1
2016-12-01 10:49:47 ASH 850-BSI2 10000000 6/4 1Com 5 7.5 1
2016-12-01 10:49:56 ASH 850-BSI3 10000000 6/4 Stb 5 7.5 1
2016-12-01 10:50:03 ASH 850-BSI1 10000000 4/4 1Com 10 10 1
2016-12-01 10:50:20 ASH 850-EMPIRE 500 4/4 2&3Com 10 10 1
2016-12-01 10:50:27 ASH 850-EMPIRE 500 4/4 2&3Com 5 5 1
2016-12-01 10:50:36 ASH 850-BSI1 10000000 4/4 Sel S 6 6 1
2016-12-01 10:50:47 ASH 850-EMPIRE 500 4/4 2&3Com 10 10 1
2016-12-01 10:52:10 ASH 850-BSI1 10000000 4/4 Frm 5 5 1
2016-12-01 10:52:21 ASH 850-BSI1 10000000 4/4 Frm 6 6 1
2016-12-01 10:52:26 ASH 850-BSI1 10000000 4/4 Frm 5 5 1
2016-12-01 10:52:39 ASH 850-BSI2 10000000 6/4 1Com 10 15 1
2016-12-01 10:52:48 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:52:54 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:53:00 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:53:06 ASH 850-OHP 15000 4/4 Sel 5 5 1
2016-12-01 10:55:31 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:59:30 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:59:37 ASH 850-OHP 15000 4/4 Sel 6 6 1
2016-12-01 10:59:48 ASH 850-BSI3 10000000 6/4 Stb 5 7.5 1
2016-12-01 10:59:54 ASH 850-BSI2 10000000 6/4 1Com 10 15 1
2016-12-01 11:00:08 ASH 850-BSI2 10000000 6/4 1Com -10 -15 -1
2016-12-01 11:00:20 ASH 850-BSI2 10000000 6/4 1Com 10 15 1
2016-12-01 11:01:02 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
我想删除log_count中带有“-1”的条目,以及前面(但可能不立即在前面)带有log count中带有“1”的对应条目。像这样:
DATE_TIME SPECIE_CODE LOAD LOAD_LIMIT THICKNESS GRADE_CODE SURFACE_MEASURE FBM LOG_COUNT
--------------------------- ----------- -------------------- -------------------- ---------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -----------
2016-12-01 10:48:32 ASH 850-OHP 15000 4/4 Sel 6 6 1
2016-12-01 10:48:43 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:48:51 ASH 850-BSI1 10000000 4/4 Sel S 5 5 1
2016-12-01 10:48:59 ASH 850-EMPIRE 500 4/4 2&3Com 6 6 1
2016-12-01 10:49:47 ASH 850-BSI2 10000000 6/4 1Com 5 7.5 1
2016-12-01 10:49:56 ASH 850-BSI3 10000000 6/4 Stb 5 7.5 1
2016-12-01 10:50:03 ASH 850-BSI1 10000000 4/4 1Com 10 10 1
2016-12-01 10:50:20 ASH 850-EMPIRE 500 4/4 2&3Com 10 10 1
2016-12-01 10:50:27 ASH 850-EMPIRE 500 4/4 2&3Com 5 5 1
2016-12-01 10:50:36 ASH 850-BSI1 10000000 4/4 Sel S 6 6 1
2016-12-01 10:50:47 ASH 850-EMPIRE 500 4/4 2&3Com 10 10 1
2016-12-01 10:52:10 ASH 850-BSI1 10000000 4/4 Frm 5 5 1
2016-12-01 10:52:21 ASH 850-BSI1 10000000 4/4 Frm 6 6 1
2016-12-01 10:52:26 ASH 850-BSI1 10000000 4/4 Frm 5 5 1
2016-12-01 10:52:39 ASH 850-BSI2 10000000 6/4 1Com 10 15 1
2016-12-01 10:52:48 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:52:54 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:53:00 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:53:06 ASH 850-OHP 15000 4/4 Sel 5 5 1
2016-12-01 10:55:31 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:59:30 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
2016-12-01 10:59:37 ASH 850-OHP 15000 4/4 Sel 6 6 1
2016-12-01 10:59:48 ASH 850-BSI3 10000000 6/4 Stb 5 7.5 1
2016-12-01 11:00:20 ASH 850-BSI2 10000000 6/4 1Com 10 15 1
2016-12-01 11:01:02 ASH 850-BSI3 10000000 6/4 Stb 6 9 1
这一切都是可行的,但如果您的源表中有一个唯一的键,那么就更容易了。这样的话,你就有了一个把手
我建议,因为这是数据迁移,可能是一次性的/有问题的任务,你可以考虑把它分解成步骤。我不会向您提供有效的SQL,因为我从您的问题中没有足够的信息来这样做,但我将这样开始:
- 列出[count]=-1的情况,因为这些是您需要匹配和删除的所有取消李>
- 理想情况下,这将是正在处理的表的唯一键列表,存储为临时(甚至永久)表李>
- 从该列表中,您可以找到要删除的匹配记录,使用窗口函数(例如ROW_NUMBER())根据时间戳(最近的时间戳)选择最佳匹配,其中存在多个匹配李>
- 有些取消可能没有匹配项,因此您可以将其放在一边并手动进行调查李>
- 甚至可能存在重复匹配(完全相同的时间戳)的情况,您需要再次进行调查李>
- 剩下的匹配现在基本上是两个列表,一个用于取消的唯一键列表,另一个用于被取消的行的相同大小的列表李>
- 删除所有这些行,或以某种方式将它们标记为不迁移
如果你没有任何唯一的密钥,那么我甚至会考虑在临时的基础上创建一个键,因为这会使它变得更容易。您可以通过以下方式来实现:
SELECT NEWID() AS temp_key, * INTO [workingTable] FROM [myTable];
在该工作表上完成所有工作,然后从该工作表迁移数据,并在该过程中删除现在的冗余密钥
好的,现在我们有了数据,我可以告诉你这在现实生活中是如何工作的 第一项工作是将数据加载到临时表中,以便我可以使用它:
SET NOCOUNT ON;
--This is the source data
IF OBJECT_ID('tempdb..#source') IS NOT NULL
DROP TABLE #source;
CREATE TABLE #source (
DATE_TIME DATETIME,
SPECIE_CODE VARCHAR(3),
[LOAD] VARCHAR(25),
LOAD_LIMIT INT,
THICKNESS VARCHAR(4),
GRADE_CODE VARCHAR(20),
SURFACE_MEASURE INT,
FBM INT,
LOG_COUNT INT);
INSERT INTO #source SELECT '2016-12-01 10:40:46', 'ASH', '850-OHP', 15000, '4/4', 'Sel', 13, 13, 1;
INSERT INTO #source SELECT '2016-12-01 10:40:52', 'ASH', '850-OHP', 15000, '4/4', 'Sel', -13, -13, -1;
INSERT INTO #source SELECT '2016-12-01 10:48:32', 'ASH', '850-OHP', 15000, '4/4', 'Sel', 6, 6, 1;
INSERT INTO #source SELECT '2016-12-01 10:48:43', 'ASH', '850-BSI3', 10000000, '6/4', 'Stb', 6, 9, 1;
INSERT INTO #source SELECT '2016-12-01 10:48:51', 'ASH', '850-BSI1', 10000000, '4/4', 'Sel S', 5, 5, 1;
INSERT INTO #source SELECT '2016-12-01 10:48:59', 'ASH', '850-EMPIRE', 500, '4/4', '2&3Com', 6, 6, 1;
INSERT INTO #source SELECT '2016-12-01 10:49:47', 'ASH', '850-BSI2', 10000000, '6/4', '1Com', 5, 7.5, 1;
INSERT INTO #source SELECT '2016-12-01 10:49:56', 'ASH', '850-BSI3', 10000000, '6/4', 'Stb', 5, 7.5, 1;
INSERT INTO #source SELECT '2016-12-01 10:50:03', 'ASH', '850-BSI1', 10000000, '4/4', '1Com', 10, 10, 1
INSERT INTO #source SELECT '2016-12-01 10:50:20', 'ASH', '850-EMPIRE', 500, '4/4', '2&3Com', 10, 10, 1;
INSERT INTO #source SELECT '2016-12-01 10:50:27', 'ASH', '850-EMPIRE', 500, '4/4', '2&3Com', 5, 5, 1;
INSERT INTO #source SELECT '2016-12-01 10:50:36', 'ASH', '850-BSI1', 10000000, '4/4', 'Sel S', 6, 6, 1;
INSERT INTO #source SELECT '2016-12-01 10:50:47', 'ASH', '850-EMPIRE', 500, '4/4', '2&3Com', 10, 10, 1;
INSERT INTO #source SELECT '2016-12-01 10:52:10', 'ASH', '850-BSI1', 10000000, '4/4', 'Frm', 5, 5, 1;
INSERT INTO #source SELECT '2016-12-01 10:52:21', 'ASH', '850-BSI1', 10000000, '4/4', 'Frm', 6, 6, 1;
INSERT INTO #source SELECT '2016-12-01 10:52:26', 'ASH', '850-BSI1', 10000000, '4/4', 'Frm', 5, 5, 1;
INSERT INTO #source SELECT '2016-12-01 10:52:39', 'ASH', '850-BSI2', 10000000, '6/4', '1Com', 10, 15, 1;
INSERT INTO #source SELECT '2016-12-01 10:52:48', 'ASH', '850-BSI3', 10000000, '6/4', 'Stb', 6, 9, 1;
INSERT INTO #source SELECT '2016-12-01 10:52:54', 'ASH', '850-BSI3', 10000000, '6/4', 'Stb', 6, 9, 1;
INSERT INTO #source SELECT '2016-12-01 10:53:00', 'ASH', '850-BSI3', 10000000, '6/4', 'Stb', 6, 9, 1;
INSERT INTO #source SELECT '2016-12-01 10:53:06', 'ASH', '850-OHP', 15000, '4/4', 'Sel', 5, 5, 1;
INSERT INTO #source SELECT '2016-12-01 10:55:31', 'ASH', '850-BSI3', 10000000, '6/4', 'Stb', 6, 9, 1;
INSERT INTO #source SELECT '2016-12-01 10:59:30', 'ASH', '850-BSI3', 10000000, '6/4', 'Stb', 6, 9, 1;
INSERT INTO #source SELECT '2016-12-01 10:59:37', 'ASH', '850-OHP', 15000, '4/4', 'Sel', 6, 6, 1;
INSERT INTO #source SELECT '2016-12-01 10:59:48', 'ASH', '850-BSI3', 10000000, '6/4', 'Stb', 5, 7.5, 1;
INSERT INTO #source SELECT '2016-12-01 10:59:54', 'ASH', '850-BSI2', 10000000, '6/4', '1Com', 10, 15, 1;
INSERT INTO #source SELECT '2016-12-01 11:00:08', 'ASH', '850-BSI2', 10000000, '6/4', '1Com', -10, -15, -1;
INSERT INTO #source SELECT '2016-12-01 11:00:20', 'ASH', '850-BSI2', 10000000, '6/4', '1Com', 10, 15, 1;
INSERT INTO #source SELECT '2016-12-01 11:01:02', 'ASH', '850-BSI3', 10000000, '6/4', 'Stb', 6, 9, 1;
现在我有29行数据要处理。下一项工作是确定取消:
--Assuming that the timestamp is unique, make a list of cancelled items
IF OBJECT_ID('tempdb..#cancelled') IS NOT NULL
DROP TABLE #cancelled;
SELECT *, CONVERT(DATETIME, NULL) AS MATCHED_DATE_TIME INTO #cancelled FROM #source WHERE LOG_COUNT = -1;
这将给我一个列表,其中包括两个要识别、匹配和删除的取消。我就是这样做的:
--Attempt to find matches
WITH BestMatch AS (
SELECT
c.*,
s.DATE_TIME AS CANDIDATE_MATCHED_DATE_TIME,
ROW_NUMBER() OVER (PARTITION BY c.DATE_TIME ORDER BY s.DATE_TIME DESC) AS MATCH_ID
FROM
#cancelled c
INNER JOIN #source s ON s.DATE_TIME <= c.DATE_TIME AND s.SPECIE_CODE = c.SPECIE_CODE AND s.[LOAD] = c.[LOAD] AND s.LOAD_LIMIT = c.LOAD_LIMIT
AND s.THICKNESS = c.THICKNESS AND s.GRADE_CODE = c.GRADE_CODE AND s.SURFACE_MEASURE = c.SURFACE_MEASURE * -1 AND s.FBM = c.FBM * -1)
UPDATE
c
SET
MATCHED_DATE_TIME = bm.CANDIDATE_MATCHED_DATE_TIME
FROM
BestMatch bm
INNER JOIN #cancelled c ON c.DATE_TIME = bm.DATE_TIME
WHERE
bm.MATCH_ID = 1; --Only pick the latest match
第一个取消是针对负载值为850-OHP的行,这里只有一个候选行,因此没有问题。第二个取消是针对负载值为850-BS12的行,这一次有两个潜在匹配。我们对它们进行排序,并为每一个分配一个匹配ID,该ID将从1开始,并为每个后续匹配递增1。MATCH_ID是按日期时间顺序排列的,因此MATCH_ID为1(10:59:54)的行是我们要删除的行,MATCH_ID为2(10:52:39)的行将保持不变
此时,您可能应该检查是否存在任何问题:
--Investigate any issues
SELECT * FROM #cancelled WHERE MATCHED_DATE_TIME IS NULL;
但是没有,所以我们继续执行删除:
--Perform the delete
DELETE FROM #source WHERE LOG_COUNT = -1;
DELETE s FROM #source s INNER JOIN #cancelled c ON c.MATCHED_DATE_TIME = s.DATE_TIME;
完成后,还剩下25行:
--Show the results
SELECT * FROM #source;
首先,获取表中出现的所有种类代码、载荷、载荷极限和厚度值的列表,其中count=-1。这些是所有拆除的规格代码、荷载、荷载极限和厚度值。然后删除所有具有此类值的行。无论它们的计数值是多少,它都将删除所有这些:
delete from MyTable
Where SPECIE_CODE + LOAD + LOAD_LIMIT + THICKNESS + GRADE_CODE
in (select SPECIE_CODE + LOAD + LOAD_LIMIT + THICKNESS + GRADE_CODE from @MyTable where counts = -1)
这里没有足够的信息来提供一个非常可靠的答案。这是一个很好的起点。出于兴趣,你为什么让它这样工作?似乎有可能出错。你的问题有些令人困惑。一方面,你说你想删除的只是删除,但后来你补充说,他们必须有关闭日期以及。这个结束日期的条件有必要吗?@Leonidas:我唯一能给你的答案就是“遗产”这个神奇的词。删除删除很容易,但我还想删除'-1'记录要撤消的原始条目。谢谢,Richard。困难来自你的第三个要点。我在我的帖子的编辑中添加了一些真实的数据,可以更好地说明我的问题。我只想删除一个匹配的条目,而不是全部。
delete from MyTable
Where SPECIE_CODE + LOAD + LOAD_LIMIT + THICKNESS + GRADE_CODE
in (select SPECIE_CODE + LOAD + LOAD_LIMIT + THICKNESS + GRADE_CODE from @MyTable where counts = -1)