基于复杂联接计数的MySQL更新列

基于复杂联接计数的MySQL更新列,mysql,sql,join,count,sql-update,Mysql,Sql,Join,Count,Sql Update,我正在用一个相当复杂的数据库模式构建一个报告。我有以下表格(为简洁起见简化) 零件有两个标识符:零件号和CLEI 所以这是同一部分: -克莱:enbyaaaaa -零件号:NT9X 搜索进入search_数据表,用户可以通过partNumber、CLEI或两者进行搜索。因此,对于上面列出的零件,您可以在search_数据中看到该零件已被搜索了4次(ID 1、2、3和4) 我需要使用该零件号或CLEI的搜索次数更新分析表的num_searches列 因此,更新后,分析表应如下所示: -------

我正在用一个相当复杂的数据库模式构建一个报告。我有以下表格(为简洁起见简化)

零件有两个标识符:零件号和CLEI

所以这是同一部分:
-克莱:enbyaaaaa
-零件号:NT9X

搜索进入search_数据表,用户可以通过partNumber、CLEI或两者进行搜索。因此,对于上面列出的零件,您可以在search_数据中看到该零件已被搜索了4次(ID 1、2、3和4)

我需要使用该零件号CLEI的搜索次数更新分析表的num_searches列

因此,更新后,分析表应如下所示:

--------------------------------------------
id   partNumber   clei          num_searches
--------------------------------------------
1    NT9X         ENBYAAAAAA    4
2    EFGH         EEEFFHI       0
3    NT9X         null          4
4    null         ENBYAAAAAA    4
我为此创建了一个有效的联接

SELECT *
FROM analytics_data a
join search_data s
on 
case when a.partNumber is not null and a.partNumber != '' THEN a.partNumber = s.partNumber END
OR
case when a.clei is not null and a.clei != '' THEN a.clei = s.clei END
我使用案例陈述来解释这一事实,即两个表中可能都有partNumber和CLEI,也可能没有。当clei在analytics中为NULL时,一个简单的A.clei=s.clei语句将在搜索中为每一行提供一个NULL的clei,而不考虑零件号

这一困境正是导致更新困难的原因。我提出了这个更新声明。我不确定它是否有效,因为它不会结束。我在几分钟后杀死了它,因为这不是一个可接受的运行时

update analytics a
  set a.num_searches = 
  (
    select count(*) from search_data s where
      (case when a.partNumber is not null and a.partNumber != '' 
       THEN a.partNumber = s.partNumber END
    OR
       case when a.clei is not null and a.clei != '' THEN a.clei = 
        s.clei END)
  ) 
我不知道接下来该怎么办。这似乎是一项简单的任务,但我厌倦了把头撞在桌子上

有什么想法吗

===========================================================================================================================

解决Nick提出的解决方案的其他细节。 我关心的是,这些部分需要大量的迭代。零件可以有一个基本代码,如“NT9X”,再加上各种族代码(2个字符),再加上另一种特征代码(2个以上字符)

所以我们可以

NT9X
NT9XAB
NT9XBB
NT9XABAA
NT9XABBB
等等。所有部件都是相同的通用部件,但功能略有不同。还有很多零件号/CLEI组合。同一零件号可以有多个CLEI代码,反之亦然

因此,我们被迫执行许多类似于
的查询。如果我想得到NT9X部分的所有引号,我有一个类似于

SELECT * FROM part_quotes WHERE partNumber LIKE 'NT9X%';
它适用于1部分。但对于像现在这样的例子,我有一个6000多个部分的列表,我需要来自十几个不同表的数据来生成一个报告,用一个查询是不可能的

因此,在您的场景中,我必须对part_numbers表执行类似于
的查询,以获得所有潜在的part匹配。然后,我必须在part_id的表连接中使用IN子句

如果不进行测试,我不知道它的效率是高还是低

我有很多存储零件信息的表格。像

vendor_quotes
internal_quotes
search_results
search_data
sales_history
repair_pricing
pricing
purchase_history
expenses

还有更多。试图构建一个报告,在这个报告中,我必须对如此多的表和聚合数据进行通配符搜索,这是一个相当令人头痛的问题。我肯定需要一个更好的方法来实现它,并将在不久的将来测试您的解决方案

您的代码似乎太复杂了,但我认为它应该可以工作。这个版本很简单:

update analytics a
  set a.num_searches = (select count(*)
                        from search_data s
                        where a.partNumber = s.partNumber or
                              a.clei = s.clei
                       );
您的数据没有空格,因此没有理由检查它们

但是,正如您所注意到的,性能相当差。相反,让我们分两部分来做。如果零件号相同,然后
clei
与零件号不匹配:

update analytics a
  set a.num_searches = ((select count(*)
                         from search_data s
                         where a.partNumber <=> s.partNumber 
                        ) +
                        (select count(*)
                         from search_data s
                         where not a.partNumber <=> s.partNumber and
                               a.clei = s.clei
                        )
                       );
更新分析a
设置a.num_searches=((选择count(*)
从搜索_数据
其中a.零件号s.零件号
) +
(选择计数(*)
从搜索_数据
其中不是a.零件号s.零件号和
a、 clei=s.clei
)
);

这个版本应该能够利用
search\u数据(partNumber,clei)
search\u数据(clei,partNumber)

您的代码似乎太复杂了,但我认为它应该可以工作。这个版本很简单:

update analytics a
  set a.num_searches = (select count(*)
                        from search_data s
                        where a.partNumber = s.partNumber or
                              a.clei = s.clei
                       );
您的数据没有空格,因此没有理由检查它们

但是,正如您所注意到的,性能相当差。相反,让我们分两部分来做。如果零件号相同,然后
clei
与零件号不匹配:

update analytics a
  set a.num_searches = ((select count(*)
                         from search_data s
                         where a.partNumber <=> s.partNumber 
                        ) +
                        (select count(*)
                         from search_data s
                         where not a.partNumber <=> s.partNumber and
                               a.clei = s.clei
                        )
                       );
更新分析a
设置a.num_searches=((选择count(*)
从搜索_数据
其中a.零件号s.零件号
) +
(选择计数(*)
从搜索_数据
其中不是a.零件号s.零件号和
a、 clei=s.clei
)
);

这个版本应该能够利用
search\u数据(partNumber,clei)
search\u数据(clei,partNumber)

这是数据库正常化的经典参数。如果您有这样一个表
零件号

CREATE TABLE part_numbers 
    (id INT, `partNumber` VARCHAR(4), `clei` VARCHAR(10));
INSERT INTO part_numbers VALUES
    (1, 'NT9X', 'ENBYAAAAAA'),
    (2, 'EFGH', 'EEEFFHI');

SELECT * FROM part_numbers

id  partNumber  clei
1   NT9X        ENBYAAAAAA
2   EFGH        EEEFFHI
3   NNTM        EGFEDGF
id  part_id     searchDate
1   1           2017-10-15
2   1           2017-11-11
3   1           2017-11-12
4   1           2017-11-15
5   3           2017-11-15
您将
search\u data
analytics
中的
partNumber
clei
字段替换为
part\u id
字段,该字段引用了
part\u number
中的
id
,因此,例如
search\u data
将如下所示:

CREATE TABLE part_numbers 
    (id INT, `partNumber` VARCHAR(4), `clei` VARCHAR(10));
INSERT INTO part_numbers VALUES
    (1, 'NT9X', 'ENBYAAAAAA'),
    (2, 'EFGH', 'EEEFFHI');

SELECT * FROM part_numbers

id  partNumber  clei
1   NT9X        ENBYAAAAAA
2   EFGH        EEEFFHI
3   NNTM        EGFEDGF
id  part_id     searchDate
1   1           2017-10-15
2   1           2017-11-11
3   1           2017-11-12
4   1           2017-11-15
5   3           2017-11-15
那么您的更新查询将是:

UPDATE analytics a
   SET num_searches = (SELECT COUNT(s.id) FROM search_data s WHERE s.part_id = a.part_id)
这将向您展示如何转换表格以使您的生活更轻松

假设你不能(或不想)改变你的表格结构,生活就会变得更加困难。您可以通过此查询()生成分析应为的表:

输出:

id  partnumber  clei        num_searches
1   NT9X        ENBYAAAAAA  4
2   EFGH        EEEFFHI     0
3   NT9X        (null)      4
4   (null)      ENBYAAAAAA  4
id  partnumber  clei        num_searches
1   NT9X        ENBYAAAAAA  4
2   EFGH        EEEFFHI     0
3   NT9X        (null)      4
4   (null)      ENBYAAAAAA  4
因此更新查询变为(注意,我们必须
连接
子查询,因为我们不能在
集合
子句中使用包含更新表的子查询)():

输出:

id  partnumber  clei        num_searches
1   NT9X        ENBYAAAAAA  4
2   EFGH        EEEFFHI     0
3   NT9X        (null)      4
4   (null)      ENBYAAAAAA  4
id  partnumber  clei        num_searches
1   NT9X        ENBYAAAAAA  4
2   EFGH        EEEFFHI     0
3   NT9X        (null)      4
4   (null)      ENBYAAAAAA  4
这是一个clas