не в состоянии определить разницу между одним и тем же значением - PullRequest
0 голосов
/ 11 июля 2019

У меня есть данные внутри столбца таблицы. Я выбираю DISTINCT этого столбца, я также ставлю LTRIM (RTRIM (col_name)), а также при написании SELECT. Но все же я получаю дубликат записи столбца.

Как мы можем определить, почему это происходит и как мы можем избежать этого?

Я пробовал функции 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 ]

2 голосов
/ 11 июля 2019

Похоже, где-то там есть юникод-символ.Сначала я скопировал и вставил значения как 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, что означает, что между c и t есть * Unicode-символ.

Итак, давайте выясним, что это такое:

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

The UNICODE функция возвращает обратно 8203, что является пробелом нулевой ширины.Я предполагаю , что вы хотите удалить их, поэтому вы можете обновить свои данные, выполнив:

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

Теперь ваш первый запрос должен работать так, как вы ожидаете.

(Iтакже предположим, что вам может потребоваться таблица соответствия для вашего статуса с внешним ключом, чтобы это не могло повториться).

DB <> fiddle

0 голосов
/ 12 июля 2019

Я имею дело с этим типом вещей все время.Для таких вещей NGrams8K и PatReplace8k и PATINDEX - ваши лучшие друзья.

Поместив то, что вы разместили в табличную переменную, мы можем проанализировать проблему:

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');

Этот запрос будет определять элементы с символами, отличными от AZ, пробелов и дефисов:

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...