我有2,500,000个产品名称,我想尝试将它们组合在一起,即找到名称相似的产品.例如,我可以有三种产品:
这实际上是相同的产品,可以合并在一起.
我的计划是使用Jaro Winkler的距离算法来实现匹配.该过程如下:
所以这有一些优化,因为它只对每个产品进行单向匹配,节省了一半的处理时间.
我把它编码并测试了它.它运作完美,并发现了数十个匹配的调查.
将1个产品与2,500,000个其他产品进行比较需要大约20秒钟,并计算出"Jaro评分".假设我的计算是正确的,这意味着它将花费一年的最佳时间来完成处理.
显然这不实用.
我让同事们查看代码,他们设法将Jaro分数计算部分的速度提高了20%.他们使这个过程成为多线程,并使其更快一点.我们还删除了一些存储的信息,将其简化为产品名称和唯一标识符列表; 这似乎对处理时间没有任何影响.
通过这些改进,我们仍然认为这需要几个月的时间来处理,我们需要花费数小时(或最多几天).
我不想详细介绍,因为我认为这不是完全相关的,但我将产品详细信息加载到列表中:
private class Product
{
public int MemberId;
public string MemberName;
public int ProductId;
public string ProductCode;
public string ProductName;
}
private class ProductList : List<Product> { }
private readonly ProductList _pl = new ProductList();
Run Code Online (Sandbox Code Playgroud)
然后我使用以下处理每个产品:
{Outer loop...
var match = _pl[matchCount];
for (int count = 1; count < _pl.Count; count++)
{
var search = _pl[count];
//Don't match …
Run Code Online (Sandbox Code Playgroud) 四个简单的SELECT语句:
SELECT 33883.50 * -1;
SELECT 33883.50 / -1.05;
SELECT 33883.50 * -1 / 1.05;
SELECT (33883.50 * -1) / 1.05;
Run Code Online (Sandbox Code Playgroud)
但结果并不如我所料:
-33883.50
-32270.000000
-32269.96773000
-32270.000000
Run Code Online (Sandbox Code Playgroud)
第三个结果似乎是值得怀疑的结果.我可以看到发生了什么,首先SQL Server评估这个:
SELECT -1 / 1.05;
Run Code Online (Sandbox Code Playgroud)
得到答案:
-0.952380
Run Code Online (Sandbox Code Playgroud)
然后它接受该答案并使用它来执行此计算:
SELECT 33883.50 * -0.952380;
Run Code Online (Sandbox Code Playgroud)
得到(错误的)答案:
-32269.96773000
Run Code Online (Sandbox Code Playgroud)
但为什么这样做呢?
我正在尝试编写一个存储过程,该过程将从任意表和列中删除前导和尾随引号.我一直收到错误,说明没有声明表名.
这是SP
create table [dbo].[test] (id nvarchar(20))
insert into dbo.test values ('"07617966004766"')
go
CREATE PROCEDURE sp_stripDoubleQuotes
@tableName sysname,
@columnName sysname
AS
BEGIN
SET NOCOUNT ON;
UPDATE @tableName
SET @columnName = SUBSTRING(@columnName, 2, LEN(@columnName))
WHERE LEFT(@columnName, 1) = '"'
UPDATE @tableName
SET @columnName = SUBSTRING(@columnName, 1, LEN(@columnName)-1)
WHERE RIGHT(@columnName, 1) = '"'
END
GO
exec [dbo].[sp_stripDoubleQuotes] N'[dbo].[test]', N'[id]'
select * from test
Run Code Online (Sandbox Code Playgroud)
我有一个已反序列化并粘贴到HashSet中的Dynamics CRM 2013审核数据列表,定义为:
private class AuditCache
{
public Guid ObjectId;
public int HistoryId;
public DateTime? DateFrom;
public DateTime? DateTo;
public string Value;
};
private HashSet<AuditCache> _ac = new HashSet<AuditCache>();
Run Code Online (Sandbox Code Playgroud)
我添加这样的数据(来自SQL Server记录集):
_ac.Add(new AuditCache{
ObjectId = currentObjectId,
HistoryId = Convert.ToInt32(dr["HistoryId"]),
DateTo = Convert.ToDateTime(dr["CreatedOn"]),
Value = value});
Run Code Online (Sandbox Code Playgroud)
我最终得到了大约一百万条记录。
接下来,我需要遍历每个Guid,并从匹配的审计数据中提取数据的子集。我有一份我在其他地方生成的Guid列表,大约有30万个要处理。我将它们存储在:
var workList = new Dictionary<Guid, DateTime>();
Run Code Online (Sandbox Code Playgroud)
...并像这样遍历它们:
foreach (var g in workList)
Run Code Online (Sandbox Code Playgroud)
然后,我需要执行此操作以提取每个Guid的子集:
List<AuditCache> currentSet = _ac.Where(v => v.ObjectId == g.Key).ToList();
Run Code Online (Sandbox Code Playgroud)
但这很慢。
填充我的初始审核数据列表大约需要1分钟,但要花费几个小时(我从未运行过它才能完成,所以这是基于处理1%数据的时间)来取出每个数据集,对其进行处理并将其喷回进入数据库表。
单步执行代码,我可以看到瓶颈似乎正在从每个Guid的列表中拉出子集。所以我的问题是,是否有更好/更有效的方法(架构?)来存储/检索我的数据集?
需要注意的一件事是,我知道Guid本质上对索引/搜索的速度很慢,但是由于Dynamics CRM的工作方式,我在使用它们方面受到了很大的限制。我想我可以创建一个词典来查找Guid并将其“转换”为整数值或类似的东西,但是我不相信这会有所帮助吗?
编辑
好的,我使用实时数据(371,901吉德)测试了三种解决方案,这些结果是每1,000吉德的平均时间。请注意,这包括对SQL Server的处理/ INSERT,因此它不是适当的基准。
Method #0 - …
Run Code Online (Sandbox Code Playgroud) 如果我运行此命令:
DECLARE @sql NVARCHAR(10) = NULL;
EXEC sp_executesql @sql;
SELECT @@ROWCOUNT;
Run Code Online (Sandbox Code Playgroud)
我希望得到0,甚至NULL也可以。但是我什么也没有,我得到1。为什么执行NULL查询会影响1行?如果我传递“适当的”(non_NULL)查询,那么它将正常工作。
背景(针对那些关心的人):这来自一个应该生成一些动态SQL以更新一行且仅更新一行的过程。我需要检查1行是否受到影响,而不是0或2或大于2。它工作正常,直到设法以某种方式设法生成NULL SQL语句,并且这被视为成功-糟糕!
实际的解决方法是在运行SQL之前检查SQL是否为非NULL,并以与1以外的结果相同的方式对待NULL语句。但是我仍然很好奇为什么它表现为这种方式。
这是我正在尝试做的一个简单示例:
CREATE TABLE daily_factors (
factor_date date,
factor_value numeric(3,1));
CREATE TABLE customer_date_ranges (
customer_id int,
date_from date,
date_to date);
INSERT INTO
daily_factors
SELECT
t.factor_date,
(random() * 10 + 30)::numeric(3,1)
FROM
generate_series(timestamp '20170101', timestamp '20210211', interval '1 day') AS t(factor_date);
WITH customer_id AS (
SELECT generate_series(1, 100000) AS customer_id),
date_from AS (
SELECT
customer_id,
(timestamp '20170101' + random() * (timestamp '20201231' - timestamp '20170101'))::date AS date_from
FROM
customer_id)
INSERT INTO
customer_date_ranges
SELECT
d.customer_id,
d.date_from,
(d.date_from::timestamp + random() * (timestamp '20210211' - …
Run Code Online (Sandbox Code Playgroud) 所以这是一个非常标准的要求; 我有一个包含地址信息的表,我想提取一个"格式化"的地址,其中所有字段都与逗号分隔符连接.
问题是某些字段可能为NULL,因此我最终会使用尾随逗号.例如,一个地址可能是"10 The Strand,London",最后没有国家,但下一个可能是"5 Fleet Street,London,England".如果我挑选出每个地址元素并假设它始终存在,那么我会将这两个地址表示为:
"5 Fleet Street ,,,,"
"10 The Strand ,,,, London,England"
从中间删除额外的逗号很简单,只是对NULL的测试.
我知道如何使用CTE或子查询在两次传递中修复尾随逗号问题,但是这可以在一次传递数据中完成吗?
以下是使用CTE的示例:
DECLARE @Address TABLE (
Name VARCHAR(255),
Line1 VARCHAR(255),
Line2 VARCHAR(255),
Line3 VARCHAR(255),
City VARCHAR(255),
Country VARCHAR(255));
INSERT INTO @Address VALUES ('Complete', 'Test 1', 'Test 2', 'Test 3', 'Oxford', 'England');
INSERT INTO @Address VALUES ('Incomplete', '22 Accacia', NULL, NULL, 'York', 'England');
INSERT INTO @Address VALUES ('Missing End', '10 Bond Street', NULL, NULL, 'London', NULL);
WITH Addresses AS
(
SELECT
CASE WHEN Name …
Run Code Online (Sandbox Code Playgroud) sql-server ×4
sql ×3
c# ×2
t-sql ×2
.net ×1
algorithm ×1
duplicates ×1
dynamics-crm ×1
fuzzy-logic ×1
grouping ×1
null ×1
postgresql ×1