Отправить 5k и более объектов по строковому разделителю в параметр SQL PROC, затем разделить, проанализировать и зациклить для каждого объекта в Query - PullRequest
0 голосов
/ 29 марта 2019

У меня есть система цитирования, где мы очищаем данные, считываемые из импортированного файла, и в каждой строке чтения в файле мы нажимаем SQL, чтобы проверить, существует ли элемент, или это опечатка / not found / etc, чтобы получить нечеткие результаты поиска для каждого вкл. Таким образом, впоследствии, и конечный пользователь может затем исправить плохие / не найденные элементы, чтобы исправить те, которые мы нашли в нечетком поиске.

При этом этот инструмент очистки используется для импорта файла CSV, который может быть где угодно от 500 записей до 10 000 записей.

Когда я делаю это в каждой строке, я многократно нажимаю на SQL, что приводит к снижению эффективности и скорости.

Я надеялся попробовать следующее для обработки одного вызова SQL и сделать все это на сервере SQL, чтобы проверить разницу в скоростях.

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

Вот как я читаю файл с тех пор, как он большой, и он быстро светится:

 using (BufferedStream bs = new BufferedStream(uploadedFile.InputStream))
 {
      using (StreamReader sr = new StreamReader(bs))
      {
            // store in array here... for later looping to the SQL lookups
      }
 }

 // After I read the entire file, then placed into array of rows,
 // the next is how i loop to lookup each match, por find best matches using fuzzy
 foreach (var baseQuoteItem in quoteDataRows)
 {
     hubContext.Clients.Client(connectionId).SendMessage(connectionId, String.Format("Reading record {0} of {1} ", callCounter.ToString(), fullRecords.ToString()));

     // service away
     var searches = _quoteEntityService.GetAssetsFromFuzzySearch(baseQuoteItem.Manufacturer, baseQuoteItem.Model, baseQuoteItem.Description).ToList();

     int totalFoundResults = searches.Count();

     baseQuoteItem.SuggestionsList = new List<QuoteEntityItemVM>();
}

Я хотел бы попробовать собрать все объекты, затем отправить их с разделителем свойств через запятую, затем каждый объект через ^. Таким образом, параметр хранимой процедуры будет иметь данные, как показано ниже:

obj.P1, obj.P2, obj.P3 ^ obj2.P!1, obj2.P2, obj2.P3 ^ 

и так далее. Затем я мог бы послать тысячи объектов со свойствами, которые мне нужны в запросе, в виде строки и просмотреть каждую сущность между ^, а затем выполнить поиск по ним, используя значения этой сущности, разделив свойства запятой.

Пример в SQL (я знаю, что синтаксис здесь неправильный, он только для демонстрационных целей ":

@OBJECTS = split(@ITEMS on ","); //now i have rows or array of all items.
* * Тысяча двадцать-одина затем
foreach(var i in @OBJECTS)
BEGIN
    do fuzzy search here for i
END

Возможно ли это и как мне это настроить?

Вот текущая хранимая процедура SQL Server, которую я использую:

ALTER PROCEDURE [dbo].[DATA_FuzzyAssetMacth] 
    @Mfr AS VARCHAR(100),
    @Model AS VARCHAR(100),
    @Desc AS VARCHAR(150)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @s1 VARCHAR(100);
    DECLARE @_MFRFIND INT;
    DECLARE @_MDNUMBER INT;
    DECLARE @MDDESC VARCHAR(150);

    DECLARE @_SEARCH VARCHAR(150);

    IF OBJECT_ID('tempdb..#TEMPPMFR') IS NOT NULL 
       DROP TABLE #TEMP

    IF OBJECT_ID('tmpdb..#TEMPPMFRMODEL') IS NOT NULL 
       DROP TABLE #TEMPPMFRMODEL

    IF((SELECT COUNT(*) FROM Products_OurProducts_Products AS POP 
        WHERE POP.Manufacturer = @Mfr 
          AND POP.ManufacturerPartNumber = @Model) > 0)
    BEGIN
        --DIG DONE AND RETURN
        SELECT 
            POP.Manufacturer, POP.ManufacturerPartNumber, 
            POP.Description AS ManufacturerDescription, 
            CONVERT(money, POP.Price) AS Price, POP.ItemType, 
            CAST('1' AS BIT) AS MfrFound, CAST('1' AS BIT) AS ModelFound, 
            CAST('-1' AS int) AS Score 
        FROM 
            Products_OurProducts_Products AS POP
        WHERE 
            POP.Manufacturer = @Mfr 
            AND POP.ManufacturerPartNumber = @Model
    END
    ELSE
        -- CHECK IF WE HAVE MATCH AT MFR LEVEL, THEN MODEL, THEN DESCRIPTION
        -- IF WE DO NOT HAVE IT AT ONE LEVEL, APPLY SELECT TO BASE LEVELS, THEN FUZZY SEARCH NEXT LEVEL
        IF((SELECT COUNT(*) FROM Products_OurProducts_Products AS POP 
            WHERE POP.Manufacturer = @Mfr) > 0)
        BEGIN
            IF((SELECT COUNT(*) FROM Products_OurProducts_Products AS POP 
                WHERE POP.Manufacturer = @Mfr 
                  AND POP.ManufacturerPartNumber = @Model) > 0)
                --DIG DONE AND RETURN
                SELECT 
                    POP.Manufacturer, POP.ManufacturerPartNumber, 
                    POP.Description AS ManufacturerDescription, 
                    CONVERT(money, POP.Price) AS Price, POP.ItemType, 
                    CAST('1' AS BIT) AS MfrFound, CAST('1' AS BIT) AS ModelFound,
                    CAST('-1' AS int) AS Score 
                FROM 
                    Products_OurProducts_Products AS POP
                WHERE  
                    POP.Manufacturer = @Mfr 
                    AND POP.ManufacturerPartNumber = @Model
            ELSE
            -- WE NEED TO USE FUZZY ON MODEL NUMBER
            BEGIN
                SELECT 
                    PMFR.Manufacturer, PMFR.ManufacturerPartNumber, 
                    PMFR.Description AS ManufacturerDescription, 
                    CONVERT(money, PMFR.Price) AS Price, 
                    PMFR.ItemType, CAST('1' AS BIT) AS MfrFound, 
                    CAST('0' AS BIT) AS ModelFound
                INTO 
                    #TEMPPMFR
                FROM 
                    Products_OurProducts_Products AS PMFR
                WHERE 
                    PMFR.Manufacturer = @Mfr;

                SELECT TOP 5 
                    P.Manufacturer, P.ManufacturerPartNumber, 
                    P.ManufacturerDescription, P.Price, P.ItemType, 
                    P.MfrFound, P.ModelFound, fms.score AS Score
                FROM 
                    #TEMPPMFR AS P
                CROSS APPLY 
                    (SELECT
                         dbo.FuzzyControlMatch(@Model, P.ManufacturerPartNumber) AS score) AS fms
                ORDER BY 
                    fms.score DESC
            END
        END
        ELSE
            -- IF HAVE A FUZZY AT MFR, THEN WE NEED TO GRAB BEST CHOICE AND GO DOWN. 
            -- WE COULD HAVE POSSIBLY CANDIDATES FOR THIS SO WHEN TO STOP RECURSIVENESS AND SAY ADDING NEW ENTRY?   
        BEGIN
            --AT MOMENT JUST RETURN TOP FOUND MFR THEN SELECT FROM THAT TO SEE RESULT TESTS
            DECLARE @TEMP_MFRNAME VARCHAR(100);

            --FIRST LETS SEE IF SENT MODEL EXIST AND IF SO, PULL THAT THEN RANK AGAINST MFR FOR IT
            IF((SELECT COUNT(*) FROM Products_OurProducts_Products AS POP WHERE POP.ManufacturerPartNumber = @Model) > 0)
                BEGIN
                    --DIG DONE AND RETURN
                    SELECT PMFR.Manufacturer, PMFR.ManufacturerPartNumber, PMFR.Description AS ManufacturerDescription, CONVERT(money,PMFR.Price) AS Price, PMFR.ItemType, CAST('0' AS BIT) AS MfrFound, CAST('1' AS BIT) AS ModelFound 
                    INTO #TEMPPMFRMODEL
                    FROM Products_OurProducts_Products AS PMFR
                    WHERE PMFR.ManufacturerPartNumber = @Model;

                    SELECT top 5 P.Manufacturer, P.ManufacturerPartNumber,P.ManufacturerDescription, P.Price, P.ItemType, P.MfrFound, P.ModelFound, fms.score  as Score
                    FROM #TEMPPMFRMODEL AS P
                    CROSS APPLY (select dbo.FuzzyControlMatch(@Mfr, P.Manufacturer) AS score) AS fms
                    ORDER by fms.score desc
                END
            --THEN SEE IF EXIST USING FUZZY FOUND MFR, TO SEEK MODEL NUMBER ETC.
        END

    IF OBJECT_ID('tempdb..#TEMPPMFR') IS NOT NULL 
        DROP TABLE #TEMP

    IF OBJECT_ID('tmpdb..#TEMPPMFRMODEL') IS NOT NULL 
        DROP TABLE #TEMPPMFRMODEL
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...