У меня есть система цитирования, где мы очищаем данные, считываемые из импортированного файла, и в каждой строке чтения в файле мы нажимаем 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