无法识别相同值之间的差异

时间:2019-07-11 17:21:17

标签: sql-server tsql

我在表的列中有数据。我选择该列的DISTINCT,同时在编写SELECT时也放置LTRIM(RTRIM(col_name))。但是我仍然得到重复的列记录。

我们如何确定它发生的原因以及如何避免它?

我尝试了RTRIM,LTRIM,UPPER功能。仍然没有帮助。

查询:

select distinct  LTRIM(RTRIM(serverstatus)) 
from SQLInventory

输出:

Development
Staging
Test
Pre-Production
UNKNOWN
NULL
Need to be decommissioned
Production

Pre-Produc​tion
Decommissioned
Non-Production
Unsupported Edition

2 个答案:

答案 0 :(得分:2)

好像在某处有一个Unicode字符。我最初将这些值复制并粘贴为varchar,然后执行以下操作:

SELECT DISTINCT serverstatus
FROM (VALUES('Development'),
            ('Staging'),
            ('Test'),
            ('Pre-Production'),
            ('UNKNOWN'),
            ('NULL'),
            ('Need to be decommissioned'),
            ('Production'),
            (''),
            ('Pre-Produc​tion'),
            ('Decommissioned'),
            ('Non-Production'),
            ('Unsupported Edition'))V(serverstatus);

有趣的是,这返回了以下值:

Development
Staging
Test
Pre-Production
UNKNOWN
NULL
Need to be decommissioned
Production

Pre-Produc?tion
Decommissioned
Non-Production
Unsupported Edition

请注意,其中一个值为Pre-Produc?tion,表示ct之间存在一个Unicode字符。

所以,让我们找出它是什么:

SELECT 'Pre-Produc​tion', N'Pre-Produc​tion',
       UNICODE(SUBSTRING(N'Pre-Produc​tion',11,1));

UNICODE函数返回8203,这是一个零宽度的空间。我假设您要删除这些内容,因此您可以执行以下操作来更新数据:

UPDATE SQLInventory
SET serverstatus = REPLACE(serverstatus, NCHAR(8203), N'');

现在,您的第一个查询应该可以按预期工作。

(我还建议您可能需要一个带有外键的状态查询表,以免再次发生这种情况。)

DB<>fiddle

答案 1 :(得分:0)

我一直都在处理这类事情。对于诸如NGrams8KPatReplace8kPATINDEX这样的事物,您是最好的朋友。

将您发布的内容放入表变量中,我们可以分析问题:

DECLARE @table TABLE (txtID INT IDENTITY, txt NVARCHAR(100));

INSERT @table (txt) 
VALUES ('Development'),('Staging'),('Test'),('Pre-Production'),('UNKNOWN'),(NULL),
('Need to be decommissioned'),('Production'),(''),('Pre-Produc​tion'),('Decommissioned'),
('Non-Production'),('Unsupported Edition');

此查询将识别带有A-Z,空格和连字符以外的字符的项目:

SELECT t.txtID, t.txt
FROM   @table AS t
WHERE  PATINDEX('%[^a-zA-Z -]%',t.txt) > 0;

这将返回:

txtID       txt
----------- -------------------------------------------
10          Pre-Produc​tion

要确定坏字符,我们可以像这样使用NGrams8k

SELECT      t.txtID, t.txt, ng.position, ng.token -- ,UNICODE(ng.token)
FROM        @table                 AS t
CROSS APPLY dbo.NGrams8K(t.txt,1) AS ng
WHERE       PATINDEX('%[^a-zA-Z -]%',ng.token)>0;

哪个返回:

txtID  txt               position             token
------ ----------------- -------------------- ---------
10     Pre-Produc​tion    11                   ?

PatReplace8K可以非常轻松快捷地清理此类内容。首先请注意此查询:

SELECT      OldString = t.txt, p.NewString
FROM        @table AS t
CROSS APPLY dbo.patReplace8K(t.txt,'%[^a-zA-Z -]%','') AS p
WHERE       PATINDEX('%[^a-zA-Z -]%',t.txt) > 0;

哪个在我的系统上返回:

OldString          NewString
------------------ ----------------
Pre-Produc?tion    Pre-Production

要解决此问题,您可以像这样使用patreplace8K:

UPDATE      t
SET         txt = p.newString
FROM        @table                                     AS t
CROSS APPLY dbo.patReplace8K(t.txt,'%[^a-zA-Z -]%','') AS p
WHERE       PATINDEX('%[^a-zA-Z -]%',t.txt) > 0;