我有两张桌子。
表格提醒
username -- alert -- timestamp
abc -- 3 -- 2017-12-09 13:10:42
def -- 3 -- 2017-12-12 18:10:00
xyz -- 3 -- 2017-12-11 11:00:00
表格页
username -- url -- timestamp
abc -- home -- 2017-12-09 13:18:42
abc -- home -- 2017-12-13 19:03:10
def -- home -- 2017-12-13 13:33:00
我想要做的是展示usernames
和alerts
上找到的pages
。但是,我只需要在pages
上显示其时间戳最接近alerts
时间戳的行。
这意味着
abc -- 3 -- 2017-12-09 13:10:42 -- home -- 2017-12-09 13:18:42
def -- 3 -- 2017-12-12 18:10:00 -- home -- 2017-12-13 13:33:00
到目前为止我做了什么
SELECT alerts.username, alerts.alert, alerts.timestamp, pages.url, pages.timestamp
FROM alerts
join pages on pages.username = alerts.username
WHERE username IN(SELECT DISTINCT username
FROM pages
WHERE url = 'home'
AND timestamp >
alerts.timestamp)
GROUP BY username
但是这个查询不会返回最接近的,而是随机返回的(我猜最新的)。
我该如何解决这个问题?
答案 0 :(得分:0)
SELECT DISTINCT a.username, abs(a.timestamp-p.timestamp) as difference
FROM alerts a
JOIN pages p ON p.username = a.username
HAVING difference = min(difference)
上面的查询将选择带有邮票之间绝对差异的用户名,然后它将仅返回差异最小的行。
答案 1 :(得分:0)
您可能想尝试使用窗口函数:
select * from (
select
p.username,
p.timestamp pages_timestamp,
p.url,
a.timestamp alerts_timestamp,
a.alert,
row_number() over (partition by p.username order by abs(p.timestamp - a.timestamp)) rn
from alerts a
join pages p on a.username = p.username) t
where t.rn = 1
我们正在加入用户名表来计算每个匹配对的时差。我们为分区中的每一行分配一个row_number
,该行共享相同的用户名(按时差排序),只选择行号为1的行(即时差最小的行)
如果每个表中每个用户有足够的行,您可能需要在select表中添加where abs(p.timestamp - a.timestamp) < SOME_LIMIT
。
更新:如果您运行MySQL 5.6或类似版本,那么您对窗口函数运气不佳,您将不得不应用旧的逐个连接技巧:< / p>
select
p.username,
p.url,
p.timestamp pages_timestamp,
a.alert,
a.timestamp alerts_timestamp
from (
select
p.username,
min(abs(p.timestamp - a.timestamp)) min_diff
from alerts a
join pages p on a.username = p.username
group by p.username) t
join pages p on p.username = t.username
join alerts a on a.username = p.username
where abs(p.timestamp - a.timestamp) = t.min_diff
请注意,如果(且仅当)pages
中有多个行与同一username
的警报中的某些行具有相同的时间差,则会为每个用户生成重复的行。
答案 2 :(得分:0)
这是另一个想法 - 创建一个临时表,两个时间戳(每个用户)之间的时间差最小 - 然后链接到临时表和WHERE子句通过匹配值获得最接近的时间戳计算。
代码示例:
SELECT A.UserName, MIN(CONVERT(DECIMAL(6,2),P.TimeStamp -A.timestamp)) TimeDif
INTO #Temp1
FROM Alerts A INNER JOIN Pages P ON A.UserName = P.username
GROUP BY A.UserName
SELECT A.UserName, A.Alert, P.url, P.timestamp
FROM Alerts A INNER JOIN
Pages P ON A.UserName = P.username INNER JOIN
#Temp1 T ON A.UserName = T.UserName
WHERE T.TimeDif = CONVERT(DECIMAL(6,2),P.TimeStamp -A.timestamp)