-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.xml
297 lines (282 loc) · 15.5 KB
/
index.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>切糕的打工笔记</title>
<link>https://randy-whitesugar.github.io/</link>
<description>Recent content on 切糕的打工笔记</description>
<generator>Hugo -- gohugo.io</generator>
<language>zh-cn</language>
<lastBuildDate>Tue, 19 Jul 2022 00:11:03 +0800</lastBuildDate>
<atom:link href="https://randy-whitesugar.github.io/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>SQL处理连续性问题:从经典面试题开始拓展思路</title>
<link>https://randy-whitesugar.github.io/post/sql_q1/</link>
<pubDate>Tue, 19 Jul 2022 00:11:03 +0800</pubDate>
<guid>https://randy-whitesugar.github.io/post/sql_q1/</guid>
<description><blockquote>
<p>前言:连续登录问题是一个经典的SQL面试题,相信有些同学已经背下答案了,我们先把套路过一下,再拓展开来,希望给大家一点点启发。</p>
</blockquote>
<h4 id="一题目">一、题目</h4>
<h5 id="1题目常见形式">1、题目常见形式</h5>
<p> 1)查询连续登录7天的用户<br>
2)查询连续登录7天以上的用户</p>
<h5 id="2数据样例表名login">2、数据样例(表名login)</h5>
<table>
<thead>
<tr>
<th style="text-align:center">userid</th>
<th style="text-align:center">login_time</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-02 11:00:23</td>
</tr>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-03 12:00:23</td>
</tr>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-03 13:00:23</td>
</tr>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-04 12:00:23</td>
</tr>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-06 12:00:23</td>
</tr>
<tr>
<td style="text-align:center">0002</td>
<td style="text-align:center">2021-05-06 12:00:23</td>
</tr>
<tr>
<td style="text-align:center">0002</td>
<td style="text-align:center">2021-05-08 12:00:23</td>
</tr>
</tbody>
</table>
<h4 id="二思路梳理">二、思路梳理</h4>
<h5 id="1数据预处理">1、数据预处理</h5>
<p> 首先,比较明确的是,登录时间信息要简化下,每个人每天登录只保留一条记录就好。<br>
代码如下:<br>
<em>注:以下sql代码采用hive sql语法,是工作常用的,面试也会认可</em></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">select
</span></span><span class="line"><span class="cl"> userid
</span></span><span class="line"><span class="cl"> , split(login_time, &#39; &#39;)[0] as login_date
</span></span><span class="line"><span class="cl">from login
</span></span><span class="line"><span class="cl">group by
</span></span><span class="line"><span class="cl"> userid
</span></span><span class="line"><span class="cl"> , split(login_time, &#39; &#39;)[0]
</span></span></code></pre></td></tr></table>
</div>
</div><p>结果表:</p>
<table>
<thead>
<tr>
<th style="text-align:center">userid</th>
<th style="text-align:center">login_date</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-03</td>
</tr>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-04</td>
</tr>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-06</td>
</tr>
<tr>
<td style="text-align:center">0002</td>
<td style="text-align:center">2021-05-06</td>
</tr>
<tr>
<td style="text-align:center">0002</td>
<td style="text-align:center">2021-05-08</td>
</tr>
</tbody>
</table>
<h5 id="2如何从语法角度定义连续">2、如何从语法角度定义连续?</h5>
<p>我们知道sql的语法通常是把每一条记录独立看待的,如果想表示不同记录之间的关系,通常有两种办法:<br>
1)窗口函数(好用但是有局限)<br>
2)自连接(更万能但是更麻烦)<br>
=&gt; 我们先用窗口函数法做一下,慢慢拓展开来,尝试把问题通用化</p>
<h5 id="3所谓标准解法">3、所谓标准解法</h5>
<p><strong>窗口函数法</strong>(网上流传的标准做法,需要聪明的小脑袋瓜灵光乍现一下)<br>
<strong>显然:
对于某一个用户登录产生的一个连续日期序列,日期 - 序列号 * 天数 = 常数(其等于序列开始的前一天)</strong><br>
Q:这时候有小伙伴要举手了,不就是等差数列嘛,有那么多性质,为啥非找这么一个性质呢?<br>
A:简单来说两个原因:<br>
1)我们需要的是一个序列的共同特征,所谓共同特征最好的体现就是一个共同的特征值<br>
2)好算呀,序列号可以直接用窗口函数row_number()得出(不熟悉窗口函数的同学可以去翻翻教程哈)<br>
<strong>此题标准答案</strong><br>
代码如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">select
</span></span><span class="line"><span class="cl"> userid
</span></span><span class="line"><span class="cl"> , login_date
</span></span><span class="line"><span class="cl"> , date_sub(login_date, rn) as sequence_feature
</span></span><span class="line"><span class="cl">from
</span></span><span class="line"><span class="cl">(
</span></span><span class="line"><span class="cl"> select
</span></span><span class="line"><span class="cl"> userid
</span></span><span class="line"><span class="cl"> , login_date
</span></span><span class="line"><span class="cl"> , row_number() over(partition by userid order by login_date) as rn
</span></span><span class="line"><span class="cl"> from tmp_user_login_distinct_days
</span></span><span class="line"><span class="cl">) as a
</span></span><span class="line"><span class="cl">;
</span></span></code></pre></td></tr></table>
</div>
</div><p>结果表:</p>
<table>
<thead>
<tr>
<th style="text-align:center">userid</th>
<th style="text-align:center">login_date</th>
<th style="text-align:center">sequence_feature</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-03</td>
<td style="text-align:center">2021-05-02</td>
</tr>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-04</td>
<td style="text-align:center">2021-05-02</td>
</tr>
<tr>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-06</td>
<td style="text-align:center">2021-05-05</td>
</tr>
<tr>
<td style="text-align:center">0002</td>
<td style="text-align:center">2021-05-06</td>
<td style="text-align:center">2021-05-05</td>
</tr>
<tr>
<td style="text-align:center">0002</td>
<td style="text-align:center">2021-05-08</td>
<td style="text-align:center">2021-05-07</td>
</tr>
</tbody>
</table>
<p>有了这个序列特征值,就想算什么算什么啦,注意分组条件:<br>
1)连续登陆天数:
<code>group by userid, sequence_feature =&gt; count(distinct login_date)</code><br>
2)连续登录最后一天:
<code>group by userid, sequence_feature =&gt; max(login_date)</code></p>
<h4 id="三题目拓展v1">三、题目拓展v1</h4>
<p>现在我们面对的需求发生了一点变化,不是连续登录日期问题啦,而是连续操作问题。</p>
<h5 id="1题目描述">1、题目描述</h5>
<p> 数据源是一个工单操作日志,id是工单号,userid是操作工号,op_time是操作时间。已知同一个工单可以由多个人流转操作(即A操作几次后可以转给B,B操作几次后可以转给C,以此类推)。我们把同一个人对同一个工单的连续操作视为一个操作周期(或称一个工作量),希望取出所有工单的所有操作周期的最后一次操作时间(即操作周期结束时间)。</p>
<h5 id="2数据样例表名operation">2、数据样例(表名operation)</h5>
<table>
<thead>
<tr>
<th style="text-align:center">id</th>
<th style="text-align:center">userid</th>
<th style="text-align:center">op_time</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">30213029</td>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-02 11:00:23</td>
</tr>
<tr>
<td style="text-align:center">30213029</td>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-03 12:00:23</td>
</tr>
<tr>
<td style="text-align:center">30213029</td>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-03 13:00:23</td>
</tr>
<tr>
<td style="text-align:center">67813098</td>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-04 12:00:23</td>
</tr>
<tr>
<td style="text-align:center">67813098</td>
<td style="text-align:center">0001</td>
<td style="text-align:center">2021-05-06 12:00:23</td>
</tr>
<tr>
<td style="text-align:center">67813098</td>
<td style="text-align:center">0002</td>
<td style="text-align:center">2021-05-06 12:00:23</td>
</tr>
<tr>
<td style="text-align:center">67813098</td>
<td style="text-align:center">0002</td>
<td style="text-align:center">2021-05-08 12:00:23</td>
</tr>
</tbody>
</table>
<p>叮叮!给大家思考一下,可以私信我答案,下一篇博文更新我的代码~</p>
</description>
</item>
<item>
<title>关于我</title>
<link>https://randy-whitesugar.github.io/about/</link>
<pubDate>Sat, 16 Jul 2022 00:56:50 +0800</pubDate>
<guid>https://randy-whitesugar.github.io/about/</guid>
<description></description>
</item>
<item>
<title>关于我</title>
<link>https://randy-whitesugar.github.io/post/self_introduction/</link>
<pubDate>Fri, 15 Jul 2022 20:12:35 +0800</pubDate>
<guid>https://randy-whitesugar.github.io/post/self_introduction/</guid>
<description><h4 id="关于我">关于我</h4>
<p>大家好,我是切糕(* ̄︶ ̄),目前是网易的一名数据分析师,在职一年。<br>
时间过得真快,转眼就工作一周年啦,突然想开个博客,目的有两个:<br>
一来,工作中用的最多的就是SQL,又是一年秋招季,想和大家在SQL方面做一些分享和探讨,共同学习进步;<br>
二来,无论是工作还是生活,有个地方逼着自己写点东西,思考也好,感悟也罢,能够证明自己没有虚度光阴。<br>
总之,我乐于探讨有趣的技术问题,也喜欢相声、小品、京剧、话剧等舞台艺术,一直在努力做一个灵魂有趣的新生代农民工啦!</p>
</description>
</item>
</channel>
</rss>