mysql更新列

2hh7jdfx  于 2021-06-25  发布在  Mysql
关注(0)|答案(2)|浏览(252)

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

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

零件有两个标识符:partnumber和clei
所以这是同一部分:
-克莱:恩比亚
-零件号:nt9x
搜索进入搜索数据表,用户可以通过partnumber、clei或两者进行搜索。因此,对于上面列出的部件,您可以在search\ u数据中看到该部件已被搜索了4次(ids 1、2、3和4)。
我需要用该零件号或clei的搜索次数更新分析表的num\u 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在analytics中为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上。
有什么想法吗?

更多细节,以解决尼克提出的解决方案。

我担心的是,这些部分需要大量的迭代。一个零件可以有一个基本代码,如“nt9x”,再加上各种族代码(2个字符),再加上另一种特征代码(2个以上字符)。
所以我们可以

NT9X
NT9XAB
NT9XBB
NT9XABAA
NT9XABBB

等等。它们都是相同的通用部件,但功能略有不同。还有很多零件号/clei组合。同一零件号可以有多个clei代码,反之亦然。
因此,我们不得不做很多类似的查询。如果我想得到nt9x部分的所有引用,我有一个类似于。。。

SELECT * FROM part_quotes WHERE partNumber LIKE 'NT9X%';

它只适合一部分。但是对于像现在这样的例子,我有一个6000多个部分的列表,我需要来自十几个不同表的数据来生成一个报告,这是不可能用一个查询来完成的。
所以在您的场景中,我必须对part\u numbers表进行类似的查询,以获得所有可能的part匹配。然后,我将不得不在表联接中的第\u id部分使用in子句。
如果不进行测试,我不知道它的效率是高还是低。
我有很多表存储零件信息。像这样的table。。。

vendor_quotes
internal_quotes
search_results
search_data
sales_history
repair_pricing
pricing
purchase_history
expenses

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

7kjnsjlb

7kjnsjlb1#

你的代码看起来太复杂了,但我认为应该可以用。这个版本很简单:

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

这个版本应该能够利用上的索引 search_data(partNumber, clei) 以及 search_data(clei, partNumber) .

5vf7fwbs

5vf7fwbs2#

这是数据库正常化的经典论据。如果你有table 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

你换了 partNumber 以及 clei 中的字段 search_data 以及 analytics 带一个字段 part_id 引用的 idpart_numbers 比如说 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 条款)(小提琴):

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

相关问题