MySQL如何查询某列的修改次数

Posted

技术标签:

【中文标题】MySQL如何查询某列的修改次数【英文标题】:How to query number of changes in a column in MySQL 【发布时间】:2012-08-24 20:08:21 【问题描述】:

我有一个存储具有两个属性的项目的表。所以表格有三列:

 item_id  |  property_1  |  property_2  |  insert_time
  1       |   10         |  100         |  2012-08-24 00:00:01
  1       |   11         |  100         |  2012-08-24 00:00:02
  1       |   11         |  101         |  2012-08-24 00:00:03
  2       |   20         |  200         |  2012-08-24 00:00:04
  2       |   20         |  201         |  2012-08-24 00:00:05
  2       |   20         |  200         |  2012-08-24 00:00:06

也就是说,每次任何项目的 either 属性发生变化时,都会插入一个新行。还有一列存储插入时间。现在我想获取property_2 中的更改次数。对于上表,我应该得到

item_id  |  changes_in_property_2
 1       |    2
 2       |    3

我怎样才能得到这个?

【问题讨论】:

你的表上是否有 id 列,或者每条记录都有一个 datetime 字段?只是好奇,否则有没有办法对记录进行排序? 鉴于示例数据中的第 4 行和第 6 行之间没有区别,您将无法确定更改。您可能需要添加某种可排序的时间信息,以便按顺序比较前一个值和下一个值。 由于第 4 行和第 6 行是相同的,因此确定更改将是非常困难。您需要另一列或不同的记录方法。 @Tom,@ahillman3,@njk 我确实有一列插入时间。我刚刚编辑了我的问题。 @seanhawk 你桌上的钥匙是什么? 【参考方案1】:

这将告诉您输入了多少不同的值。但是,如果将其更改回以前的值,则不会将其视为新更改。如果没有数据的年表,很难做更多的事情。

select item_id, count(distinct property_2)
from Table1
group by item_id

【讨论】:

我确实有一列插入时间。我刚刚编辑了我的问题。【参考方案2】:

这是最接近您想要的结果的方法。但是我应该注意,您是在询问基于item_idproperty_2 的更改次数。如果您正在严格分析这两列,那么item_id 1 只有 1 处更改,item_id 2 有 2 处更改。您需要将结果扩展为由 property_1 聚合。希望这个fiddle 能告诉你原因。

SELECT a.item_id,  
  SUM(
    CASE 
      WHEN a.property_2 <> 
        (SELECT property_2 FROM tbl b 
          WHERE b.item_id = a.item_id AND b.insert_time > a.insert_time LIMIT 1) THEN 1
      ELSE 0
    END) AS changes_in_property_2
FROM tbl a
GROUP BY a.item_id

【讨论】:

【参考方案3】:

我的看法:

SELECT 
    i.item_id,
    SUM(CASE WHEN i.property_1 != p.property_1 THEN 1 ELSE 0 END) + 1
      AS changes_1,
    SUM(CASE WHEN i.property_2 != p.property_2 THEN 1 ELSE 0 END) + 1
      AS changes_2
FROM items i
LEFT JOIN items p
  ON p.time = 
    (SELECT MAX(q.insert_time) FROM items q 
        WHERE q.insert_time < i.insert_time AND i.item_id = q.item_id)
GROUP BY i.item_id;

i 中未选择的每个项目都有一个条目,该条目没有前任。不过,这很重要,这就是总和增加的原因。

【讨论】:

@Anime p.time 指的是什么?如果item_id 没有变化怎么办?好像没有变化你也会加1。 我知道,这令人困惑,但如果您仔细查看 OP 给出的数字,项目的每个第一个条目本身都被视为更改。如您所见,即使从100101 只有一次飞跃,他也希望对 (item_1, property_2) 进行 2 次更改。对于i 中的每个条目,p.time 指的是同一项目的前一个条目的 insert_time。因此,由于我们使用的是内连接,因此不会出现没有前任的条目,因此我们必须手动将它们添加到总和中(并且我们知道每个条目总是正好为 1)。 我刚刚注意到最好使用LEFT JOIN,以防一个项目只有一个条目。它不会弄乱总和,因为没有前任的条目将具有 p.property_1p.property_2NULL,这会导致 CASE ... WHEN 构造返回 0。【参考方案4】:

我会这样做,使用用户定义的变量来跟踪前一行的值。

SELECT item_id, MAX(c) AS changes_in_property_2
FROM (
    SELECT IF(@i = item_id, IF(@p = property_2, @c, @c:=@c+1), @c:=1) AS c, 
        (@i:=item_id) AS item_id,
        (@p:=property_2) 
    FROM `no_one_names_their_table_in_sql_questions` AS t,
    (SELECT @i:=0, @p:=0) AS _init
    ORDER BY insert_time
) AS sub
GROUP BY item_id;

【讨论】:

以上是关于MySQL如何查询某列的修改次数的主要内容,如果未能解决你的问题,请参考以下文章

修改DataTable中某列的数据类型.

如何更改SQL中某列的值

SQL如何查询出某一列中不同值出现的次数?

如何获取MySQL行,直到某列的总和超过阈值?

更改DataTable某列的值。C#

c# 怎么更改DataTable 中某列的值?