简体   繁体   English

如何选择日期间隔

[英]How to select a date interval

This is my table: 这是我的表:

+------+--------+-------------------+
| user | item   | date_time         |
|   10 |     01 | 10-10-10 20:10:05 |
|   10 |     02 | 10-10-10 20:10:10 |
|   10 |     03 | 10-10-10 20:10:10 |
|   20 |     02 | 10-10-10 20:15:10 |
|   20 |     02 | 10-10-10 20:20:10 |
|   30 |     10 | 10-10-10 20:01:10 |
|   30 |     20 | 10-10-10 20:01:20 |
|   30 |     30 | 10-10-10 20:05:20 |
+------+--------+-------------------+

I want to do a query that return a user that took multiple items in a 1min interval, like this result: 我想做一个查询,返回一个在1分钟间隔内占用多个项目的用户,如下所示:

+------+--------+-------------------+
| user | item   | date_time         |
|   10 |     01 | 10-10-10 20:10:05 |
|   10 |     02 | 10-10-10 20:10:10 |
|   10 |     03 | 10-10-10 20:10:10 |
|   30 |     10 | 10-10-10 20:01:10 |
|   30 |     20 | 10-10-10 20:01:20 |
+------+--------+-------------------+

How can I do this? 我怎样才能做到这一点?


Edit 编辑

And if I want to only display users that appear 2 or more times on this output? 如果我只想显示在此输出上出现2次或更多次的用户?

Example: 例:

+------+--------+-------------------+
| user | item   | date_time         |
|   10 |     01 | 10-10-10 20:10:05 |
|   10 |     02 | 10-10-10 20:10:10 |
|   10 |     03 | 10-10-10 20:10:10 |
+------+--------+-------------------+

You'll have to join the table against itself (let's call the table aliases T1 and T2). 你必须自己加入表(让我们调用表别名T1和T2)。 Then write a WHERE clause to filter only rows where T1.user is equal T2.user and the absolute value of the difference between T1.date_time and T2.date_time is less than a minute. 然后编写一个WHERE子句来仅过滤T1.user等于T2.user的行,并且T1.date_time和T2.date_time之间的差值的绝对值小于一分钟。

But the problem is that every row will get selected, because you have no primary key on your table, thus there's no way to detect when a row is getting joined with itself. 但问题是每一行都会被选中,因为你的表上没有主键,因此没有办法检测一行是否与自身连接。 Create a primary key (an autonumber sequence will work just fine), and add a condition to the WHERE clause that says T1.id <> T2.id . 创建一个主键(一个自动编号序列将正常工作),并向WHERE子句添加一个条件,说明T1.id <> T2.id

So in (untested) code form: 所以在(未经测试的)代码形式中:

SELECT *
FROM stuff T1, stuff T2
WHERE T1.user = T2.user
  AND ABS(UNIX_TIMESTAMP(T1.date_time) - UNIX_TIMESTAMP(T2.date_time)) < 60
  AND T1.id <> T2.id;

Yes, you need to add a primary key (id) as suggested by @Will. 是的,你需要按照@Will的建议添加主键(id)。

To get each item once (and only once) regardless of how many matches there were within the 1-minute window, try a subquery instead of a full join: 要获得每个项目一次(并且仅一次),无论1分钟窗口内有多少匹配,请尝试子查询而不是完整连接:

Select user,item,date_time from my_table t1
  where id in (select t2.id from my_table t2,my_table t3
      where t2.id <> t3.id and t2.user = t3.user 
           and abs(t2.date_time - t3.date_time) < 60)

--edit-- For your edited question, that depends on exactly what you mean. --edit--对于您编辑的问题,这取决于您的意思。 Do you mean "users who bought 3 or more items within 60 seconds" or "users who appear more than 2 times in the output". 您的意思是“在60秒内购买3件或更多件商品的用户”或“在输出中出现2次以上的用户”。 The latter is easy to do: assume the results of the above query are saved in a temporary table (or view) "temp1": 后者很容易做到:假设上述查询的结果保存在临时表(或视图)“temp1”中:

select * from my_table where user in 
    (select user from temp1 group by user having count(*) > 2);

let's try that one: 让我们尝试一下:

SELECT * FROM myTable  
JOIN (SELECT MAX(date_time) AS maxi, MIN(date_time) AS mini, user AS uid FROM myTable GROUP BY uid) AS otherTable  
ON date_time<=maxi AND date_time>=mini AND user = uid AND UNIX_TIMESTAMP(maxi) - UNIX_TIMESTAMP(mini) < 60  
GROUP BY uid, date_time

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM