小编Ric*_*ell的帖子

试图优化模糊匹配

我有2,500,000个产品名称,我想尝试将它们组合在一起,即找到名称相似的产品.例如,我可以有三种产品:

  • 亨氏焗豆400克;
  • Hz Bkd Beans 400g;
  • 亨氏豆400克.

这实际上是相同的产品,可以合并在一起.

我的计划是使用Jaro Winkler的距离算法来实现匹配.该过程如下:

  • 列出内存中所有产品名称的大清单;
  • 选择列表中的第一个产品;
  • 将它与列表中的每个产品进行比较并计算出"Jaro分数";
  • 报告任何具有高匹配(例如0.95f或更高)的产品;
  • 转到下一个产品.

所以这有一些优化,因为它只对每个产品进行单向匹配,节省了一半的处理时间.

我把它编码并测试了它.它运作完美,并发现了数十个匹配的调查.

将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)

c# algorithm grouping duplicates fuzzy-logic

15
推荐指数
1
解决办法
1117
查看次数

为什么SQL Server会改变操作顺序和装箱方式呢?

四个简单的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)

但为什么这样做呢?

sql sql-server sql-server-2014

6
推荐指数
1
解决办法
338
查看次数

用于删除引号的存储过程

我正在尝试编写一个存储过程,该过程将从任意表和列中删除前导和尾随引号.我一直收到错误,说明没有声明表名.

这是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)

这是一个小提琴的链接: 链接到小提琴

sql sql-server stored-procedures

6
推荐指数
1
解决办法
157
查看次数

我需要从中提取子集的大量GUID和其他数据,最快的方法是什么?

我有一个已反序列化并粘贴到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)

.net c# dynamics-crm

5
推荐指数
2
解决办法
898
查看次数

为什么@@ ROWCOUNT使用sp_executesql为NULL语句返回1?

如果我运行此命令:

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语句。但是我仍然很好奇为什么它表现为这种方式。

sql t-sql sql-server null

5
推荐指数
1
解决办法
77
查看次数

我需要使用 PostgreSQL 尽快在日期范围之间添加大量值,最好的方法是什么?

这是我正在尝试做的一个简单示例:

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)

postgresql postgresql-performance

5
推荐指数
1
解决办法
49
查看次数

如何从SQL Server数据库中获取逗号分隔的单个地址,其中某些元素可能为NULL

所以这是一个非常标准的要求; 我有一个包含地址信息的表,我想提取一个"格式化"的地址,其中所有字段都与逗号分隔符连接.

问题是某些字段可能为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)

t-sql sql-server

4
推荐指数
1
解决办法
3860
查看次数