【问题标题】:Compare first record to other rows based on dates for every customer using mysql使用 mysql 根据每个客户的日期将第一条记录与其他行进行比较
【发布时间】:2016-05-17 20:05:17
【问题描述】:

我有一张客户访问表。

对于每个客户,我想将第一条记录的 post_vst_dt 与第二条记录的 vst_beg_dt 进行比较。

如果第二条访问记录的vst_beg_dt 大于第一条记录的post_vst_dt,则需要选择两条记录,否则必须将第一条记录的post_vst_dt 与第三条记录的vst_beg_dt 进行比较。

基于相同的条件检查,要么必须选择第一条和第三条记录,要么只选择第一条记录。

这需要针对所有客户进行检查,并且每个客户可以进行任意次数的访问。

这可以使用 SQL 或带有循环和游标的 mysql 过程来完成吗?有人可以帮忙吗。

| Visit_ID | Cust_ID | Vst_Beg_Dt | Vst_End_Dt | Post_vst_Dt |
|----------+---------+------------+------------+-------------|
|      445 |     545 | 2015-11-23 | 2015-11-28 | 2016-01-12  |
|      198 |     545 | 2016-01-07 | 2016-01-12 | 2016-02-26  |
|      271 |     545 | 2016-01-19 | 2016-01-29 | 2016-03-14  |
|      841 |     291 | 2015-09-08 | 2015-09-12 | 2015-10-27  |
|      987 |     291 | 2015-12-19 | 2015-12-23 | 2016-02-06  |
|      211 |     291 | 2015-12-26 | 2016-01-06 | 2016-02-20  |
|      122 |     291 | 2016-02-25 | 2016-02-27 | 2016-04-12  |

预期的输出是

| Visit_ID | Cust_ID | Vst_Beg_Dt | Vst_End_Dt |
|----------+---------+------------+------------|
|      445 |     545 | 2015-11-23 | 2015-11-28 |
|      271 |     545 | 2016-01-19 | 2016-01-29 |
|      841 |     291 | 2015-09-08 | 2015-09-12 |
|      987 |     291 | 2015-12-19 | 2015-12-23 |
|      122 |     291 | 2016-02-25 | 2016-02-27 |

“第一”是指每个客户的最小 vst_beg_dt 记录

【问题讨论】:

  • 什么记录应该被认为是第一个,什么 - 第二个?
  • 为什么 Post_vst_Dt 存储为字符串格式而不是日期?
  • 第一条记录是最小 vst_beg_dt 的记录;客户的第一、第二、第三条记录由 vst_beg_dt 排序
  • Post_vst_Dt 日期格式可以更改,在示例中是错误的
  • stackoverflow.com/questions/7745609/… 显示如何找到每个客户的第一行

标签: mysql compare


【解决方案1】:

我认为这是与How to do the Recursive SELECT query in MySQL? 类似的问题。

我喜欢leftclickbenanswer to that problem。这是对该查询的修改,我认为它适用于您的情况。

SELECT
    v.visit_id, @cust := v.cust_id cust_id, v.vst_beg_dt, v.vst_end_dt,
    @post := v.post_vst_dt post_vst_dt
FROM (SELECT * FROM visit ORDER BY cust_id, vst_beg_dt) v
JOIN (SELECT @cust := 0, @post := NULL) tmp
WHERE v.cust_id != @cust OR v.vst_beg_dt > @post;

本质上,您对结果进行排序,以便每个客户的访问都在一起并按日期排序。然后在每一行上将@cust@post 变量分别更新为cust_idpost_vst_dt。最后过滤结果以仅包含与前一行(客户的最早条目)不具有相同cust_id 或具有大于前一个post_vst_dtvst_beg_dt 的行。

实际上我有点惊讶这可行,但它似乎为您的示例数据返回了正确的值。

【讨论】:

  • 非常感谢马特!这确实有效。我在想必须使用游标来循环。我唯一的问题是,如果除了客户 ID 之外还有 1 个以上的密钥,您需要如何修改?
  • 我不确定。你能用另一个关键列的细节来编辑你的问题吗?
  • 好的就行。如果可能的话,你能解释一下这个简单的查询是如何递归工作的吗?特别是。我无法理解带有 or 条件的 where 子句。谢谢。
  • 据我了解,它并不是真正的递归。当它遍历选择时,对于它选择的每一行,它将@cust 设置为该行的cust_id,并将@post 设置为该行的post_vst_dt。然后WHERE 子句过滤掉后续记录,如果它具有相同的cust_id 并且vst_beg_dt 早于先前选择的行的post_vst_dt。最初的 SELECT @cust := 0, @post := NULL "table" 是必需的,因为当 WHERE 子句第一次运行时,不会有前一行。只要确保没有客户拥有cust_id0
  • 没问题。很高兴听到我可以帮助您解决问题,而且我学到了一些新东西,这总是很棒。在 Stack Overflow 上说“谢谢”的既定方式是投票或接受答案。对于每个问题,您只能接受一个答案,这会将其从“未回答”问题列表中移除,并为发布答案的用户提供一些声誉积分。
猜你喜欢
  • 2012-06-03
  • 2018-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多