2012-08-24 32 views
3

我有一个存储具有两个属性的项目的表。因此,该表有三列:如何查询MySQL中列中的更改数

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 

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

item_id | changes_in_property_2 
1  | 2 
2  | 3 

我该如何得到这个?

+0

你在表格上有一个id列,或者每个记录有一个datetime字段吗?只是好奇,否则有没有办法对记录进行排序? – Tom

+1

考虑到示例数据中第4行和第6行之间没有差异,您将会遇到问题。您可能需要添加某种可排序的按时间顺序排列的信息以允许来回遍历,以便比较上一个值和下一个值。 – ahillman3

+0

由于第4行和第6行是相同的,所以很难确定变化。您需要另一列或不同的录制方法。 – Kermit

回答

0

这会告诉你输入了多少个不同的值。如果它被改回到先前的值,它不会被算作新的改变。没有数据的年代表,很难做更多。

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

我确实有一列插入时间。我刚刚编辑了我的问题。 –

0

这是最接近我可以得到您想要的结果。但是,我应该注意到,您正在根据item_id要求更改为property_2。如果您正在严格分析这两列,则item_id 1和2更改只有1个更改item_id 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 
0

我的看法:

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选择每个项目,有没有前一个一个条目。尽管这是一个变化,但这也是为什么这些和会增加的原因。

+0

@Anime p.time是指什么?如果“item_id”没有更改会怎么样?看起来你会加1,即使没有变化。 – Kermit

+0

我知道,这很令人困惑,但如果仔细观察OP给出的数字,则每个项目的第一个条目本身就被认为是一个变化。正如你所看到的,即使从“100”到“101”只有一个跳跃,他也希望对“(item_1”,“property_2”)进行2次更改。 对于'i'中的每个条目,'p.time'指同一项目的前一个条目的insert_time。因此,由于我们使用的是内部联接,因此不会显示前缀的条目,因此我们必须手动将它们添加到总和中(并且我们知道每个项目总是只有1)。 –

+0

我刚刚注意到,如果一个项目只有一个条目,最好做一个'LEFT JOIN'。它不会混淆总和,因为没有前置任务的条目会将'p.property_1'和'p.property_2'设置为'NULL',这会导致'CASE ...WHEN'构造返回0。 –

0

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

SELECT item_id, MAX(c) AS changes_in_property_2 
FROM (
    SELECT IF(@i = item_id, IF(@p = property_2, @c, @c:[email protected]+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;