MySQL同表相鄰數據查詢或計算(用戶下相鄰訂單的時間差舉例)

這裏主要介紹一下,在一張數據表下對相鄰的數據進行一個相關查詢和計算;
拿一個在電商中最常見的情況,計算一下用戶首單和第二單的時間間隔這樣的數據來舉例,如下:

id customer_id created_at
1 1 2017-07-21 09:43:02
2 12 2017-07-25 11:37:48
3 10 2017-07-25 11:43:41
4 1 2017-07-27 01:27:22
5 10 2017-07-27 07:46:45
6 1 2017-07-27 10:21:37
7 12 2017-07-27 13:26:19

查詢用戶首單和第二單的時間間隔:

SELECT
	m.customer_id,
	sfo.created_at as '首單時間',
	m.created_at as '第二單時間',
	(unix_timestamp(m.created_at) - unix_timestamp(sfo.created_at))/86400 as '兩單相差天數'
	
FROM
	sales_flat_order m 
LEFT JOIN 
	sales_flat_order sfo on m.customer_id = sfo.customer_id and sfo.created_at < m.created_at
WHERE
	(
		SELECT
			count(*)
		FROM
			sales_flat_order n
		WHERE
			m.customer_id = n.customer_id
			AND m.created_at > n.created_at
	) = 1
GROUP BY m.customer_id

查詢結果是:

customer_id 首單時間 第二單時間 兩單時間差
1 2017-07-21 09:43:02 2017-07-27 01:27:22 5.6558
12 2017-07-25 11:37:48 2017-07-27 13:26:19 2.0754
10 2017-07-25 11:43:41 2017-07-27 07:46:45 1.8355

整個原理如下:

  1. 將一張表查詢兩次得到兩組數據,分別爲別名m和別名n的兩組數據;
  2. 以m爲主,用n的數據和m的數據作對比,通過created_at的判斷過濾掉一些無用數據;
  3. 使用count()函數統計滿足條件的數據個數;
  4. 統計數爲1時說明n表中比m表中時間小的只有1條,m中的該條數據也就是該用戶下的第二筆訂單;
  5. 通過LEFT JOIN聯表,通過created_at找到比第二單更早的一單也就是用戶的首單;
  6. 利用unix_timestamp把得到的兩條數據的created_at做差,得到了兩筆訂單的時間間隔;

下面做了一下拓展,可以查詢任意相連的兩筆訂單的時間間隔:

SELECT
	m.customer_id,
	m.created_at as '後一單時間',
	SUBSTRING_INDEX(
		GROUP_CONCAT(sfo.created_at ORDER BY sfo.created_at DESC),
		',',
		1
	) as '前一單時間',
	(unix_timestamp(m.created_at) - unix_timestamp(
		SUBSTRING_INDEX(
			GROUP_CONCAT(sfo.created_at ORDER BY sfo.created_at DESC),
			',',
			1
		)
	))/86400 as '兩單相差天數'
FROM
	sales_flat_order m 
LEFT JOIN 
	sales_flat_order sfo on m.customer_id = sfo.customer_id and sfo.created_at < m.created_at
WHERE
	(
		SELECT
			count(*)
		FROM
			sales_flat_order n
		WHERE
			m.customer_id = n.customer_id
			AND m.created_at > n.created_at
	) = 2
GROUP BY m.customer_id;

得到數據如下:

customer_id 後一單時間 前一單時間 兩單時間差
1 2017-07-27 10:21:37 2017-07-27 01:27:22 0.3710

這裏判斷的是統計數爲2的,也就是用戶的第二單和第三單的時間間隔計算,因爲用戶10和12只有兩單所以結果中無這兩個用戶;

整個原理如下:

  1. 將一張表查詢兩次得到兩組數據,分別爲別名m和別名n的兩組數據;
  2. 以m爲主,用n的數據和m的數據作對比,通過created_at的判斷過濾掉一些無用數據;
  3. 使用count()函數統計滿足條件的數據個數;
  4. 篩選之後m中得到的是第三筆訂單;
  5. 通過LEFT JOIN聯表,通過created_at找到比第三筆訂單時間早的訂單,這裏會從sfo中得到兩筆訂單;
  6. 利用GROUP_CONCAT函數每組訂單中各得到的兩筆訂單利用created_at進行降序排序,然後得到通過‘,’連接的兩條數據的時間,如下:
2017-07-27 01:27:22,2017-07-21 09:43:02
  1. 使用SUBSTRING_INDEX函數通過’,'將數據拆分再拿到第一條數據,也就是第二筆訂單的時間了;
  2. 利用unix_timestamp對created_at作差,得到兩筆訂單的時間間隔;

這只是我想到的應對這種場景通過SQL語句進行查詢的方法,如果有小夥伴有更好的方法或者改進的方法,歡迎小夥伴留言,謝謝啦!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章