сравнение данных через функцию - PullRequest
0 голосов
/ 13 апреля 2010

У меня есть два набора данных (местоположения) в отдельных таблицах, и мне нужно сравнить, совпадают они или нет. У меня есть UDF, который выполняет вычисления на основе 5 значений из каждой таблицы.

Как мне выполнить выборку с помощью этого udf?

мой udf в основном определяется ....

ALTER FUNCTION [dbo].[MatchRanking]
(
        @Latitude       FLOAT
    ,   @Longitude      FLOAT
    ,   @Postcode       VARCHAR(16)
    ,   @CompanyName    VARCHAR(256)
    ,   @TelephoneNumber VARCHAR(32)
    ,   @Latitude2      FLOAT
    ,   @Longitude2     FLOAT
    ,   @Postcode2      VARCHAR(16)
    ,   @CompanyName2   VARCHAR(256)
    ,   @TelephoneNumber2 VARCHAR(32)

)
RETURNS INT
WITH EXECUTE AS CALLER
AS
BEGIN

    DECLARE @RetVal INT
    DECLARE @PostcodeVal INT
    SET @RetVal = 0
    SET @PostcodeVal = 0

    SET @RetVal = @RetVal + dbo.FuzzyLogicStringMatch(@CompanyName, @CompanyName2)

    IF @RetVal = 1 AND dbo.TelephoneNoStringMatch(@TelephoneNumber, @TelephoneNumber2) = 1
        RETURN 5
    ELSE
        IF @RetVal = 1 AND dbo.FuzzyLogicStringMatch(@Postcode, @Postcode2) = 1
            RETURN 5
        ELSE
            IF @RetVal = 1 AND ROUND(@Latitude,4) = ROUND(@Latitude2,4) AND ROUND(@Longitude,4) = ROUND(@Longitude2,4)
                RETURN 5
            ELSE
                IF (@RetVal = 1 AND ROUND(@Latitude,4) = ROUND(@Latitude2,4)) OR (@RetVal = 1 AND ROUND(@Longitude,4) = ROUND(@Longitude2,4))
                    SET @RetVal = 2
                ELSE
                BEGIN                   
                    IF ROUND(@Latitude,4) = ROUND(@Latitude2,4)
                        SET @RetVal = @RetVal + 1
                    IF ROUND(@Longitude,4) = ROUND(@Longitude2,4)
                        SET @RetVal = @RetVal + 1
                    SET @RetVal = @RetVal + dbo.TelephoneNoStringMatch(@TelephoneNumber, @TelephoneNumber2)
                    SET @RetVal = @RetVal + dbo.FuzzyLogicStringMatch(@Postcode, @Postcode2)
                END

    RETURN @RetVal
END

Это предыдущий код, который я пытаюсь исправить:

        SELECT li.LImportId, l.LocationId, dbo.MatchRanking(li.Latitude, li.Longitude, li.[Name], li.Postcode, li.TelephoneNumber,
                                l.Latitude, l.Longitude, l.CompanyName, l.Postcode, l.TelephoneNumber 
                    ) AS [MatchRanking]
          FROM @LocImport li
          LEFT JOIN [Location] l
            ON lI.[Latitude] = l.[Latitude]
            OR lI.[Longitude] = l.[Longitude]
            OR lI.[Postcode] = l.[Postcode]
            OR lI.[Name] = l.[CompanyName]
            OR lI.[TelephoneNumber] = l.[TelephoneNumber]

Ответы [ 4 ]

0 голосов
/ 14 апреля 2010

Одна вещь, которую мы сделали, - создала отдельную таблицу для хранения результатов перекрестного соединения, поэтому их нужно только рассчитать один раз. Затем найдите работу, которая выполняется каждую ночь, чтобы собрать новые записи и заполнить их всеми старыми записями. Ведь лат / лонги не будут меняться (за исключением случайного типа, который может найти и исправить ночная работа), и нет смысла делать этот расчет каждый раз, когда вы запускаете запрос, чтобы найти расстояния, когда вычисление всегда будет одинаковым для большинства чисел. Как только эти данные находятся в таблице, вы можете легко выполнить запрос очень быстро. Заполнение таблицы в первый раз может занять некоторое время.

0 голосов
/ 13 апреля 2010

Лично я бы сделал такое нечеткое сопоставление данных за несколько проходов.

-создание внешней таблицы, содержащей ключи для соответствующих записей -вберите все точно совпадающие и вставьте ключи в таблицу внешних ссылок

- «нечеткие» критерии и поиск снова, но только в тех записях, которые еще не нашли совпадения в внешней ссылке.

- полоскать и повторять, расширяя и / или размывая ваши критерии до тех пор, пока полученные совпадения не станут мусором.

0 голосов
/ 14 апреля 2010

Сначала вам придется скрестить две таблицы (m и n дает m x n сравнений) и сравнить, чтобы найти совпадения - другого простого способа на самом деле не существует.

Однако, с мета-пониманием данных, их интерпретации и ваших целей, если вы сможете каким-то образом отфильтровать свой набор, чтобы довольно легко исключить элементы из перекрестного соединения, это помогло бы - особенно если есть что-то, что должно быть точным сопоставить или любым способом разделить данные так, чтобы элементы в разных разделах никогда не сравнивались (т. е. сравнение местоположения в США и Европе всегда имело бы ранг совпадения 0)

Я бы сказал, что вы можете использовать Lat и Long для полного исключения, если они различаются на определенную величину, но похоже, что они используются для улучшения рейтинга совпадений, а не для отрицательного исключения предметов из ранжирования совпадений.

А скалярные функции (ваши FuzzyMatches), вызываемые повторно (как в перекрестном соединении с многомиллионными строками), чрезвычайно дороги.

Мне кажется, что вы могли бы извлечь первое совпадение и другое внутреннее в вашем перекрестном соединении (и, если возможно, встроенном, а не как UDF), чтобы оптимизатор запросов мог их несколько оптимизировать в сочетании с перекрестное соединение вместо черного ящика, называемого mxn times.

Другая возможность заключается в предварительном извлечении только отдельных пар телефонных номеров, пар почтовых индексов и т. Д.

SELECT Postcode1, Postcode2, dbo.FuzzyLogicStringMatch(Postcode1, Postcode2) AS MatchRank
FROM (
    SELECT DISTINCT Postcode AS Postcode1
    FROM Table1
) AS Postcodes1
CROSS JOIN
(
    SELECT DISTINCT Postcode AS Postcode2
    FROM Table2
) AS Postcodes2

Если ваша функция симметрична, вы можете еще больше сократить это пространство, в котором вызывать UDF, с некоторой дополнительной работой (проще, если таблица является самосоединением, вы просто используете верхний правый треугольник).

Теперь у вас есть минимальный набор сравнений для вашего скалярного UDF, который нужно вызвать. Поместите этот результат в таблицу, индексированную по двум столбцам.

Вы можете сделать подобное для всех ваших наборов параметров UDF. Если определение функции не меняется, вам нужно только добавлять новые комбинации в вашу таблицу с течением времени, превращая дорогой скалярный вызов функции в поиск таблиц на относительно медленных растущих данных. Вы даже можете использовать оператор CASE для отклика на встроенный вызов UDF, если в таблице поиска нет записи - так что вы можете решить, сохранять ли таблицы поиска полными или нет.

0 голосов
/ 13 апреля 2010

Что было не так с вашим оригинальным JOIN? это должно работать намного быстрее, чем эта функция.

Это должно сделать это, но я думаю, что это будет очень медленно:

SELECT
...
FROM Table1             t1
    CROSS JOIN Table2   t2
WHERE dbo.MatchRanking(t1.Latitude ,..,..,t2.Latitude ,..)=1 --"1" or whatever return value is a match
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...