我正在努力构建一个具有相当复杂的数据库模式的报告。我有下表(为简洁起见,进行了简化)。
Table: search_data
------------------------------------------
id partNumber clei searchDate
------------------------------------------
1 NT9X null 2017-10-15
2 NT9X ENBYAAAAAA 2017-11-11
3 null ENBYAAAAAA 2017-11-12
4 NT9X null 2017-11-15
5 NNTM null 2017-11-15
------------------------------------------
Table: analytics
--------------------------------------------
id partNumber clei num_searches
--------------------------------------------
1 NT9X ENBYAAAAAA 0
2 EFGH EEEFFHI 0
3 NT9X null 0
4 null ENBYAAAAAA 0
部件有 2 个标识符:partNumber 和 CLEI
所以这将是相同的部分:
- CLEI:ENBYAAAAAA
- 零件编号:NT9X
搜索进入search_data表,用户可以通过partNumber、CLEI或两者进行搜索。因此,对于上面列出的部分,您可以在 search_data 中看到该部分已被搜索了 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
我使用 CASE 语句来解释以下事实:任一表中可能同时存在也可能不存在partNumber 和CLEI。当 clei 在分析中为 NULL 时,一个简单的 a.clei = s.clei 语句将在搜索中为我提供带有 NULL clei 的每一行,而不管partNumber。
这种困境是导致更新困难的原因。我想出了这个更新声明。我不确定它是否有效,因为它不会完成。几分钟后我就杀死了它,因为这不是可接受的运行时间。
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)
)
我不知道从这里该去哪里。这似乎是一项简单的任务,但我厌倦了把头撞在 table 上。
有什么想法吗?
================================================== =========================
解决 Nick 提议的解决方案的更多详细信息。
我担心的是这些部分需要进行多次迭代。零件可以有一个基本代码,如“NT9X”,加上各种系列代码(2 个字符),再加上其他各种特征代码(另外 2 个字符)。
所以我们可以有
NT9X
NT9XAB
NT9XBB
NT9XABAA
NT9XABBB
等等。所有部件都是相同的通用部件,但功能略有不同。还有很多零件号/CLEI 组合。同一部件号可以有多个 CLEI 代码,反之亦然。
因此,我们被迫执行大量LIKE查询。如果我想获取 NT9X 部分的所有报价,我有一个查询,例如...
SELECT * FROM part_quotes WHERE partNumber LIKE 'NT9X%';
对于 1 部分来说效果很好。但对于像现在这样的情况,我有一个包含 6000 多个零件的列表,并且需要来自十几个不同表的数据来生成报告,这是不可能通过单个查询来完成的。
因此,对于您的场景,我必须对part_numbers表执行LIKE查询才能获取所有潜在的部分匹配。然后,我必须在part_id 的表连接中使用IN 子句。
如果没有进行测试,我不知道它的效率是否会更高或更低。
我有很多存储零件信息的表。表格如...
vendor_quotes
internal_quotes
search_results
search_data
sales_history
repair_pricing
pricing
purchase_history
expenses
还有更多。尝试构建一个必须对如此多的表和聚合数据进行通配符搜索的报告是相当令人头疼的。我肯定需要一种更好的方法来做到这一点,并将在不久的将来测试您的解决方案。
最佳答案
这是数据库正确规范化的经典论点。如果您有一个像这样的表part_numbers
:
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
并且您将 search_data
和 analytics
中的 partNumber
和 clei
字段替换为字段 part_id
引用了 part_numbers
中的 id
,例如 search_data
看起来像这样:
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)
此 SQLFiddle 向您展示如何转换表格以使您的生活更轻松。
假设您不能(或不想)更改表结构,那么生活就会变得更加困难。您可以使用此查询生成分析应类似于的表 (SQLFiddle):
SELECT a.id, a.partnumber, a.clei, COUNT(s.id) AS num_searches
FROM analytics a
LEFT JOIN analytics a2
ON a.partnumber = a2.partnumber OR a.clei = a2.clei
LEFT JOIN search_data s
ON s.partnumber = a2.partnumber OR s.clei = a2.clei
WHERE a2.partnumber IS NOT NULL AND a2.clei IS NOT NULL
GROUP BY a.id
输出:
id partnumber clei num_searches
1 NT9X ENBYAAAAAA 4
2 EFGH EEEFFHI 0
3 NT9X (null) 4
4 (null) ENBYAAAAAA 4
因此更新查询变为(请注意,我们必须JOIN
子查询,因为我们不能在SET
子句中使用包含更新表的子查询)(SQLFiddle ):
UPDATE analytics a4 JOIN (SELECT a.id AS id, COUNT(s.id) AS num_searches
FROM analytics a
LEFT JOIN analytics a2
ON a.partnumber = a2.partnumber OR a.clei = a2.clei
LEFT JOIN search_data s
ON s.partnumber = a2.partnumber OR s.clei = a2.clei
WHERE a2.partnumber IS NOT NULL AND a2.clei IS NOT NULL
GROUP BY a.id) AS c
SET a4.num_searches = c.num_searches
WHERE a4.id = c.id
SELECT * FROM analytics
输出:
id partnumber clei num_searches
1 NT9X ENBYAAAAAA 4
2 EFGH EEEFFHI 0
3 NT9X (null) 4
4 (null) ENBYAAAAAA 4
关于MySQL 根据复杂连接的计数更新列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50287767/