我对Server很陌生,我试图从表中删除副本,但是有一些条件,我对如何将这些条件应用于查询表示怀疑。
我需要从Users表中删除副本,例如:
Id Code Name SysName
-----------------------------
1 D1 N1
2 D1
3 D1 N1 N-1
4 E2 N2
5 E2 N2
6 E2 N2
7 X3
8 X3 N-3
9
10
11 Z4 W2 N-4-4
12 Z4 W2 N-44在上表中:对于D1代码,我希望保留ID=3,它填充了所有列(代码、名称和SysName),并删除ID=1和ID=2
对于E2代码,我希望保留其中的任何一个,并删除两个重复的
对于X3代码,保留具有SysName=N-3的代码
对于ID=9,ID=10 (空代码和所有空的,删除所有)
对于Z4代码,删除ID=11并保留N-44 Sysname
最后一件事,我有一个FK和其他表,所以我认为我需要首先从用户获得所有Id,从第二个依赖表中删除这些Id,最后从用户表中删除这些Id。
你对如何实现这个目标有什么想法吗?我不会假装解决方案,而是一个结构代码或类似的示例/场景,任何建议对我来说都是好的。
编辑:
继续..。我有用户表:
Id Code Name SysName
-----------------------------
1 D1 N1
2 D1
3 D1 N1 N-1
4 E2 N2
5 E2 N2
6 E2 N2
7 X3
8 X3 N-3
9
10
11 Z4 W2 N-4-4
12 Z4 W2 N-44我只想保持:
Id Code Name SysName
-----------------------------
3 D1 N1 N-1
4 E2 N2
8 X3 N-3
12 Z4 W2 N-44发布于 2018-12-03 20:34:29
你是在找像
SELECT Code,
MAX(ISNULL(Name, '')) Name,
MAX(ISNULL(SysName, '')) SysName
FROM T
WHERE Code IS NOT NULL
GROUP BY Code;返回:
+------+------+---------+
| Code | Name | SysName |
+------+------+---------+
| D1 | N1 | N-1 |
| E2 | N2 | |
| X3 | | N-3 |
| Z4 | W2 | N-4-4 |
+------+------+---------+发布于 2018-12-03 20:44:52
下一个查询显示要根据下一个重要规则删除的ids列表:
1-如果用户拥有所有字段,则将删除空/空字段。
2-具有更多错误字段的用户将首先考虑删除(例如,SysName不能包含两个字段-)。
3-有更多字段为空/空的用户将首先考虑删除。
;WITH
[Ids]
AS
(
SELECT
[U].[Id]
,[Importance] =
CASE
WHEN [X].[NumberOfFilledFields] = 0
THEN -1
ELSE ROW_NUMBER() OVER (PARTITION BY [U].[Code] ORDER BY [X].[NumberOfInvalidFields], [X].[NumberOfFilledFields] DESC)
END
FROM [Users] AS [U]
CROSS APPLY
(
SELECT
[NumberOfFilledFields] =
+ CASE WHEN NULLIF([U].[Code], '') IS NULL THEN 0 ELSE 1 END
+ CASE WHEN NULLIF([U].[Name], '') IS NULL THEN 0 ELSE 1 END
+ CASE WHEN NULLIF([U].[SysName], '') IS NULL THEN 0 ELSE 1 END
,[NumberOfInvalidFields] =
+ CASE WHEN [U].[SysName] LIKE '%-%-%' THEN 1 ELSE 0 END
) AS [X]
)
SELECT
[Id]
FROM [Ids]
WHERE (1 = 1)
AND ([Importance] = -1 OR [Importance] > 1);发布于 2018-12-03 21:06:05
(任何其他答案:您可以随意借用演示程序来测试您的答案或在您的答案中使用它!)不需要重复努力!)
可以使用像row_number()这样的分析函数/窗口函数为我们想要的每条记录分配一行,并保留所有的#1行,除了代码为null的那些.用cte做这件事,然后删除。
我们通过查看拥有最多数据的记录来确定应该保存什么,如果有关联,则使用最早的ID。
With cte as (
SELECT id, code, name, sysname,
row_number() over (partition by code order by (case when name is not null then 1 else 0 end + case when sysname is not null then 1 else 0 end) desc, ID) RN
FROM users)
Delete from cte where RN <> 1 or code is null;在以下方面的成果:
+----+----+------+------+---------+
| | ID | Code | Name | Sysname |
+----+----+------+------+---------+
| 1 | 3 | D1 | N1 | N-1 |
| 2 | 4 | E2 | N2 | NULL |
| 3 | 8 | X3 | NULL | N-3 |
| 4 | 11 | Z4 | W2 | N-4-4 |
+----+----+------+------+---------+您可以使用CTE和删除将被清除的相关FK记录,然后再次使用cte并删除用户。
https://stackoverflow.com/questions/53600503
复制相似问题