文泽路小男孩的个人博客 - Tech
type: channel
link: http://www.rukihuang.xyz/index.php/category/技术/
description: 技术相关
items: 经验笔记 - 03_iView DatePicker组件数据回显日期格式错误
items: 经验笔记 - 02_axios请求发送（文件上传FormData传参）
items: 经验笔记 - 01_Vue+SpringBoot实现文件上传（单文件上传、单页面多处地方需要上传）
items: 微信小程序 - 05_网络数据请求（wx.request、get/post、跳过request合法域名校验、案例练习）
items: 微信小程序 - 04_wxss模板样式和全局配置（模板样式_rpx_@import样式导入、全局配置_window_tabBar）
items: 微信小程序 - 03_wxml模板语法（数据绑定_{{data}}、事件绑定_bindtap_bindimput、事件传参、条件渲染_wx:if_hidden、列表渲染_wx:for_wx:key）
items: 微信小程序 - 02_常用组件（view/scroll-view、swiper/swiper-item、text/rich-text、button、image、小程序三大类API）
items: 微信小程序 - 01_小程序基础（项目结构、宿主环境）
items: 牛客数据库SQL实战 51-60（substr切割字符串、group_concat组拼接、limit_offset分页、exists条件成立判断、case分支、表的复用）
items: 牛客数据库SQL实战 41-50（数据替换replace(字段,oldval,newval)、添加主键、获取两表交集intersect、获取字符串长度length(str)）

经验笔记 - 03_iView DatePicker组件数据回显日期格式错误
type: item
date: 2022-10-12T09:25:23+08:00
description: iView DatePicker组件数据回显日期格式错误1 问题描述表单提交后期需要修改，涉及到表单数据回显，其中用到了iView的DatePicker组件，在重新提交回显数据时，发生了错误，日期时间的格式不是预期的yyyy-MM-dd，而是标准时间格式Tue Sep 20 2022 00:00:00 GMT+0800(中国标准时间)，导致java后台程序时间解析报错，数据update失败。java.text.ParseException: Unparseable date: "Tue Sep 20 2022 00:00:00 GMT+0800(中国标准时间)"2 问题原因出现问题的前端代码<FormItem label="日期"> <DatePicker type="date" format="yyyy-MM-dd" placement="bottom-end" placeholder="选择日期" v-model="formItem.statusDate" @on-change="statusDateChange" ></DatePicker> (申报/公开/授权 日期) </FormItem>查阅iview官方文档发现，v-model绑定日期数据时，值为date类型，回显数据在双重绑定时，格式发生转换错误，在字符串和date类型之间不断变化，导致表单更新时好时坏。3 解决办法经过网上的查询，在这篇文章ivew日期选择器，双向绑定日期格式，执行回调后不改变格式发现同类型问题，将v-model改为:value，并配合@on-change即可<FormItem label="日期"> <DatePicker type="date" format="yyyy-MM-dd" placement="bottom-end" placeholder="选择日期" :value="formItem.statusDate" @on-change="statusDateChange" ></DatePicker> (申报/公开/授权 日期) </FormItem>

经验笔记 - 02_axios请求发送（文件上传FormData传参）
type: item
date: 2022-09-21T13:52:31+08:00
description: axios请求发送0 抽取baseURLVue项目可在项目根目录的main.js文件中抽取baseURLaxios.defaults.baseURL = 'http://localhost:8080/eduonline'1 get请求多个参数传递，一定是params表示1.1 代码示例1axios({ method: 'get', url: 'page/getPageInfo', headers: { 'content-type': 'application/json', }, params: { pos: this.position, }, }).then(res => { console.log('成功了') console.log(res) ) }, err => { console.log('错误了') console.log(err) })1.2 代码示例2//可配置参数的方式 axios.get('/user',{ params:{ ID:12345 } }).then(res => { console.log('成功了') console.log(res) ) }, err => { console.log('错误了') console.log(err) }) //或者直接在url后拼接参数 axios.get('/user?id=123') .then(res => { console.log('成功了') console.log(res) ) }, err => { console.log('错误了') console.log(err) })2 post请求post传递参数，必须用data2.1 代码示例//以json格式传入参数 axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then(res => { console.log('成功了') console.log(res) ) }, err => { console.log('错误了') console.log(err) }) //发送post请求 axios({ method: 'post', //请求方式，默认是get请求 url:'/user/12345', //地址 data:{ //参数 firstName: 'simon', lastName: 'li' } });2.1 后端接收参数为null，可以用FormData传递项目中发现前端post请求传参，后端接收不到，均为null值，此时可以通过FormData进行传参let formData = new FormData() formData.append('position', this.position) formData.append('docServerFileName', this.docServerFileName) formData.append('socServerFileName', this.socServerFileName) formData.append('vidServerFileName', this.vidServerFileName) formData.append('posResponsibility', this.posResponsibility) axios({ method: 'post', url: 'page/submitPageInfo', headers: { 'content-type': 'application/json', }, data: formData, }).then(res => { console.log('成功了') this.$Message.success('提交成功') }, err => { console.log('错误了') console.log(err) this.$Message.error('提交失败，请联系技术人员') })2.3 上传文件需修改content-type上传文件，headers里的content-type需改为multipart/form-datalet formData = new FormData() formData.append('file', this.file) axios({ method: 'post', url: 'positionLearning/videoUpload/uploadVideo', headers: { 'content-type': 'multipart/form-data', }, data: formData, }).then(res => { conso…

经验笔记 - 01_Vue+SpringBoot实现文件上传（单文件上传、单页面多处地方需要上传）
type: item
date: 2022-09-16T10:23:28+08:00
description: 后端9月初，接到单位领导的任务，要求实现一个在线教育平台，主要展示岗位教学视频，以及相关的作业指导书，并建议要配套一个后台系统方便文件的上传和管理。作为后端开发，决定使用前后端分离，前端使用vue-admin-element，后端使用Springboot+MyBatis，数据库使用Mysql，容器使用tomcat，以及部署vue项目需要的nginx，jdk使用1.8由于项目开发只有我一个人，开发过程中遇到了不少问题，但所幸都一一解决了，趁着摸鱼的空档，决定将遇到的问题和解决方法记录下来，方便之后查阅。1. SpringBoot实现文件上传参考的是这篇掘金的文章，很详细。SpringBoot实现文件上传1.1 配置类 UploadConfig限制上传文件大小，以及总的请求文件大小。/** * @author ：RukiHuang * @description：文件上传配置类 * 配置MaxFileSize等属性 * @date ：2022/9/2 9:45 */ @Configuration public class UploadConfig { @Bean public MultipartConfigElement multipartConfigElement() { MultipartConfigFactory factory = new MultipartConfigFactory(); //单个数据大小 factory.setMaxFileSize(DataSize.ofMegabytes(200)); //总上传文件的大小 factory.setMaxRequestSize(DataSize.ofGigabytes(10)); return factory.createMultipartConfig(); } } 也可以通过在 application.properties配置文件中指定#文件上传 # 文件大小设置已在UploadConfig中配置，也可在配置文件中配置 #单个文件大小 spring.servlet.multipart.max-file-size=200MB #总文件大小（允许存储文件的文件夹大小) spring.servlet.multipart.max-request-size=10240MB1.2 配置文件 application.properties指定文件上传目标路径以及允许的文件类型#文件上传的目标路径 file.upload.path=G:\\temp\\ #文件上传允许的类型 file.upload.allowType[0]=application/pdf file.upload.allowType[1]=video/mp41.3 配置文件读取 UploadProperties/** * @author ：RukiHuang * @description：文件上传 * 上传路径 * 文件格式 * @date ：2022/9/2 10:05 */ @Component @ConfigurationProperties(prefix = "file.upload") public class UploadProperties { private String path; private List<String> allowTypeList; public String getPath() { return path; } public void setPath(String path) { this.path = path; } public List<String> getAllowType() { return allowTypeList; } public void setAllowType(List<String> allowTypeList) { this.allowTypeList = allowTypeList; } } 1.4 工具类1.4.1 唯一ID生成器 IDUtils生成唯一id/** * @author ：RukiHuang * @description：唯一ID生成器 * @date ：2022/9/2 10:07 */ public class IDUtils { public static String generateUniqueId() { return UUID.randomUUID().toString() + System.currentTimeMillis(); } }1.4.2 文件名替换工具 UploadUtils替换原始文件名，避免文件名重复/** * @author ：RukiHuang * @description：文件名替换工具 避免文件…

微信小程序 - 05_网络数据请求（wx.request、get/post、跳过request合法域名校验、案例练习）
type: item
date: 2022-03-10T11:34:46+08:00
description: 01 请求限制处于安全性的考虑，小程序官方对数据接口的请求做出了两个限制：只能请求HTTPS类型的接口必须将接口的域名添加到信任列表中02 配置request合法域名配置步骤：登陆微信小程序管理后台->开发->开发设置->服务器域名->修改request合法域名注意事项：域名只支持https协议域名不能使用ip地址或者localhost域名必须经过icp备案服务器域名一个月最多可以申请5次修改03 发起get请求调用微信小程序提供wx.request()方法，可以发起get数据请求wx.request({ url: 'https://www.escook.cn/api/get',//请求的接口地址，必须基于https协议 method: 'get', //请求的方式 data:{ //发送到服务器的数据 name: 'zs', age: 22 }, success: (res) => {//请求成功之后的回调函数 console.log(res)//查看真实数据 console.log(res.data) } })04 发起post请求wx.request({ url: 'https://www.escook.cn/api/post',//请求的接口地址，必须基于https协议 method: 'post', //请求的方式 data:{ //发送到服务器的数据 name: 'zs', age: 22 }, success: (res) => {//请求成功之后的回调函数 console.log(res)//查看真实数据 console.log(res.data) } })05 页面刚加载时就请求数据在很多情况下，我们需要在页面刚加载的时候，自动请求一些初始化数据。此时需要在页面的onLoad事件中调用获取数据的函数，示例代码如下：/** * 生命周期函数——监听页面加载 */ onLoad: function(options) { this.getInfo() this.postInfo() }06 跳过request合法域名校验开启开发环境不检验请求域名、TLS版本及HTTPS证书，跳过request合法域名的校验。注意：跳过合法域名校验，只在开发和测试阶段使用07 跨域和Ajax跨域问题只存在于基于浏览器的web开发中。由于小程序的宿主环境不是浏览器，而是微信客户端，所以小程序中不存在跨域的问题。Ajax技术的核心是依赖于浏览器中的XMLHttpRequest这个对象，由于小程序的宿主环境是微信客户端，所以小程序中不能叫做“发起Ajax请求”，而是叫做“发起网络数据请求”。08 练习app.json{ "pages":[ "pages/home/home", "pages/message/message", "pages/contact/contact", ], "window":{ "navigationBarBackgroundColor": "#025D54", "navigationBarTitleText": "在线测试", "navigationBarTextStyle":"white", "backgroundColor": "#efefef", "backgroundTextStyle":"dark", "onReachBottomDistance": 50 }, "tabBar": { "list": [ { "pagePath": "pages/home/home", "text": "home", "iconPath": "images/home.png", "selectedIconPath": "images/home-active.png" }, { "pagePath": "pages/message/message", "text": "message", "iconPath": "images/message.png", "selectedIconPath": "images/message-active.png" }, { "pagePath": "pages/contact/contact", "text": "contact", "iconPath": "images/contact.png", "selectedIconPath": "images/contact-active.png" } ] }, "style": "v2", "sitemapLocation": "sitemap.json", "lazyCodeLoading": "requiredComponents" } wxml <swiper indicator-dots="true" circular="true…

微信小程序 - 04_wxss模板样式和全局配置（模板样式_rpx_@import样式导入、全局配置_window_tabBar）
type: item
date: 2022-03-07T11:52:03+08:00
description: wxss模板样式01 什么是wxsswxss是一套样式语言，用于美化wxml的组件样式，类似于网页开发的css1.1wxss和css的关系wxss具有css大部分特性，同时wxss还对css进行了扩充和修改，以适应微信小程序的开发。wxss扩展有：rpx尺寸单位@import样式导入1.1.1 什么是rpxrpx是微信小程序独有的，用来解决屏幕适配的尺寸单位实现原理：rpx把所有设备的屏幕，在宽度上等分为750份（当前屏幕的总宽度为750rpx）在小设备上，1rpx代表的宽度较小在大设备上，1rpx代表的宽度较大1.2 样式导入使用wxss提供的@import语法，可以导入外联的样式表@import后跟需要导入的外联样式表的相对路径，用;表示语句结束/* common样式 */ .username { color: red; }/* 导入样式 */ @import "/common/common.wxss";02 全局样式和局部样式2.1 全局样式定义在app.wxss中的样式为全局样式，作用于每一个页面2.2 局部样式在页面的.wxss文件中定义的样式为局部样式，只作用于当前页面注意：当局部样式和全局样式冲突时，根据就近原则，局部样式会覆盖全局样式当局部样式的权重大于或等于全局样式的权重时，才会覆盖全局样式全局配置01 全局配置文件常用配置项小程序根目录下的app.json文件是小程序的全局配置文件。常用的配置项如下：pages记录当前小程序所有页面的存放路径window全局设置小程序窗口的外观tabBar设置小程序底部的tabBar效果style是否启用新版的组件样式1.1 window "window":{ "navigationBarBackgroundColor": "#025D54", "navigationBarTitleText": "在线测试", "navigationBarTextStyle":"white", "enablePullDownRefresh": true, "backgroundColor": "#efefef", "backgroundTextStyle":"dark", "onReachBottomDistance": 50 },1.1.1 组成部分1.1.2 常用配置项属性名类型默认值说明navigationBarTitleTextString字符串导航栏标题文字内容navigationBarBackgroundColorHexColor#000000导航栏背景颜色，如#000000navigationBarTextStyleStringwhite导航栏标题颜色，仅支持black / whitebackgroundColorHexColorf#fffff窗口的背景色backgroundTextStyleStringdark下拉loading的样式，仅支持dark / lightenablePullDowntRefreshBooleanfalse是否全局开启下拉刷新onReachBottomDistanceNumber50页面上拉触底事件触发时距页面底部距离，单位为px设置路径：app.json->window1.1.3 全局开启下拉刷新功能通过手指在屏幕上的下拉滑动操作，从而重新加载页面数据的行为设置路径：app.json->window->enablePullDownRefresh设置为true注意：在app.json开启下拉刷新功能后，会作用于每个小程序页面1.1.4 设置下拉刷新背景色当全局开启下拉刷新功能之后，默认的窗口背景为白色。设置路径：app.json->window->backgroundColor16进制颜色值（#efefef）1.1.5 设置下拉刷新时loading的样式当全局开启下拉刷新功能之后，默认窗口的loading样式为白色。设置路径：app.json->window->backgroundTextStyle为dark注意：backgroundTextStyle可选值只有dark和light1.1.6 设置上拉触底的距离通过手指在屏幕上的上拉滑动操作，从而加载更多数据的行为。设置路径：app.json->window->onReachBottomDistance设置新的值注意：默认距离为50px，如果没有特殊需求，建议使用默认值1.2 tabBartabBar是移动端常见的页面效果，用于实现多页面的快速切换。通常分为：底部tabBar顶部tabBar注意：tabBar中只能配置最少2个，最多5个tab页签当渲染顶部tabBar时，不显示icon，只显示文本1.2.1 tabBar的6个组成部分backgroundColor：tabBar 的背景色select…

微信小程序 - 03_wxml模板语法（数据绑定_{{data}}、事件绑定_bindtap_bindimput、事件传参、条件渲染_wx:if_hidden、列表渲染_wx:for_wx:key）
type: item
date: 2022-03-06T21:04:00+08:00
description: wxml模板语法01 数据绑定mustache语法，双大括号绑定数据，类似于view中的插值应用场景：绑定内容绑定属性运算（三元运算、算数运算） <view>{{info}}</view> <image src="{{imgSrc}}" mode="widthFix"></image> <view>{{randomNum1 > 5 ? "数字大于5":"数字小于5"}}</view> <view>100以内的小数：{{randomNum2 * 100}}</view>data: { info: "data test", imgSrc: "https://www.baidu.com/img/pc_9c5c85e6b953f1d172e1ed6821618b91.png", randomNum1: Math.random() * 10, randomNum2: Math.random().toFixed(2) //保留2位小数 }02 事件绑定事件是渲染层到逻辑层的通讯方式。通过事件可以将用户在渲染层产生的行为，反馈到逻辑层进行业务的处理。2.1 小程序中常用的事件类型绑定方式事件描述tapbindtap或bind:tap手指触摸后马上离开，类似于html中的click事件inputbindinput或bind:input文本框的输入事件changebindchange或bind:change状态改变时触发2.2 事件对象的属性列表当事件回调触发的时候，会收到一个事件对象event，详细属性如下属性类型说明typeString时间类型timeStampInteger页面打开到触发时间所经过的毫秒数targetObject触发时间的组件的一些属性值集合currentTargetObject当前组件的一些属性值集合detailObject额外的信息touchesArray触摸事件，当前停留在屏幕中的触摸点信息的数组changedTouchesArray触摸事件，当前变化的触摸点信息的数组target和currentTarget的区别target是触发该时间的源头组件，而currentTarget是当前时间所绑定的组件。如下图，点击内部的按钮时，点击事件以冒泡的方式向外扩散，也会触发外层view的tap事件处理函数。此时，对于外层的view来说：e.target指向的是触发事件的源头组件，e.target是内部的按钮组件。e.currentTarget指向的是当前正在触发时间的那个组件，e.currentTarget是当前的view组件。2.3 bindtap语法格式在小程序中，不存在html中的onclick鼠标点击事件，而是通过tap事件来响应用户的触摸行为。通过bindtap，可以为组件绑定tap触摸事件。在页面的.js文件中定义对应的事件处理函数，事件参数通过形参event（一般简写成e）来接收 按钮 //定义按钮的事件处理函数 btnTapHandler(e) { console.log("test"); console.log(e) },2.3.1 在事件处理函数中为data中的数据赋值通过调用this.setData(dataObject)方法，给页面data中的数据重新赋值。Page({ data: { count: 0 }, //给data数据重新赋值 changeCount(e) { this.setData({ count: this.data.count + 1 }) } }2.3.2 事件传参小程序中的事件传参比较特殊，不能绑定事件的同时为事件处理函数传递参数。小程序会把bindtap的属性值，统一当做事件名来处理，相当于调用一个名称为btnHandler(123)的事件处理函数。 事件传参 小程序中的传参，可以为组件提供data-*自定义属性传参，其中*代表的是参数的名字info会被解析为参数的名字。数值2会被解析为参数的值。 事件传参 在事件处理函数中，通过event.target.dataset.参数名即可获取到具体参数的值。 事件传参 Page({ data: { count: 0 }, //事件传参 event.target.dataset.参数名，注意data-testInfo会被解析为testinfo，大写自动变小写 btnHandler(event) { console.log(event.target.dataset.testinfo); this.setData({ count: this.data.count + event.target.dataset.testinfo }) } }2.4 bindinput语法格式小程序中，通过input事件来响应文本框的输入事件通过bindinput…

微信小程序 - 02_常用组件（view/scroll-view、swiper/swiper-item、text/rich-text、button、image、小程序三大类API）
type: item
date: 2022-03-05T21:54:00+08:00
description: 组件介绍01 小程序中组件的分类视图容器基础内容表单组件导航组件媒体组件map地图组件canvas画布组件开放能力无障碍访问1.1 视图容器view普通视图区域类似于html中的div，是一个块级元素常用来实现页面的布局效果scroll-view可滚动的视图区域常用来实现滚动列表效果swiper和swiper-item轮播图容器组件和轮播图item组件1.1.1 view <view class="container1"> <view>A</view> <view>B</view> <view>C</view> </view>/* view */ /* 设置子元素样式 */ .container1 view{ width: 100px; height: 100px; text-align: center; line-height: 100px; } .container1 view:nth-child(1) { background-color: lightgreen; } .container1 view:nth-child(2) { background-color: lightyellow; } .container1 view:nth-child(3) { background-color: lightpink; } /* 设置父元素样式 */ .container1 { display: flex;/* 弹性布局*/ justify-content: space-around;/* 空间环绕*/ }1.1.2 scroll-viewwxml <scroll-view class="container2" scroll-y> <view>A</view> <view>B</view> <view>C</view> </scroll-view>wxss/* scroll-view */ /* 设置父元素样式，给scroll-view一个固定高度 */ .container2{ border: 1px solid red; width: 100px; height: 120px; } .container2 view{ width: 100px; height: 100px; text-align: center; line-height: 100px; } .container2 view:nth-child(1) { background-color: lightgreen; } .container2 view:nth-child(2) { background-color: lightyellow; } .container2 view:nth-child(3) { background-color: lightpink; }1.1.3 swiper/swiper-itemwxml <swiper class="swiper-container" indicator-dots="true"> <swiper-item> <view class="item">A</view> </swiper-item> <swiper-item> <view class="item">B</view> </swiper-item> <swiper-item> <view class="item">C</view> </swiper-item> </swiper>wxss/* swiper */ .swiper-container { height: 150px; } .item { height: 100%; text-align: center; line-height: 150px; /*行高*/ } /* 直接标签选择器进行选择 */ /* swiper-item:nth-child(1) .item{ background-color: lightgreen; } swiper-item:nth-child(2) .item{ background-color: lightskyblue; } swiper-item:nth-child(3) .item{ background-color: lightcoral; } */ /* 类选择器下 再选标签选择器 */ .swiper-container swiper-item:nth-child(1) .item{ background-color: lightgreen; } .swiper-container swiper-item:nth-child(2) .item{ background-color: lightskyblue; } .swiper-containe…

微信小程序 - 01_小程序基础（项目结构、宿主环境）
type: item
date: 2022-02-07T18:03:00+08:00
description: 微信小程序基础01 项目结构其中最重要的三个文件：pages app.json app.js推荐小程序的所有页面都存放在pages目录中，以单独的文件夹形式存在1.1 json配置文件的作用通过不同的json文件，可以对小程序项目进行不同级别的配置。小程序中有4中配置文件：app.jsonproject.config.jsonsitemap.json每个pages文件夹下的.json1.1.2 app.json全局配置，包括小程序的所有页面路径、窗口外观、界面表现、底部tab等1.1.3 project.config.json项目配置问价你，记录对小程序开发工具所作的个性化配置setting：保存了编译相关的配置projectname：项目名称appid：小程序的账号id1.1.4 sitemap.json小程序内搜索，类似于PC网页的SEO，该json用来配置小程序页面是否允许微信索引。1.1.5 页面的json文件对本页面的窗口外观进行配置，会覆盖app.json的window中相同的配置项。1.1.6 新增页面在app.json中的pages数组下，新增一条路径，保存文件后即可新增。1.1.7 修改项目首页只需要调整app.json ->pages数组中页面路径的前后顺序，即可修改项目的首页。小程序会把排在第一位的页面，当做项目首页进行渲染。1.2 wxml模板小程序框架下的标签语言，用来构建小程序页面的结构，类似于HTML。1.2.1 wxml与html的区别标签名称不同html：div, span, img, awxml: view, text, image, navigator属性节点不同超链接<navigator url="/pages/home/home"></navigator>提供了类似于vue中的模板语法数据绑定列表渲染条件渲染1.3 wxss样式微信小程序的一套样式语言，类似网页开发中的css1.3.1 wxss和css的区别新增了rpx尺寸单位css中需要手动进行像素单位的换算，如remwxss在底层支持新的尺寸单位rpx,在不同大小的屏幕上会进行自动换算提供了全局的样式和局部样式项目根目录下的app.wxss会作用于所有小程序页面局部页面的.wxss仅对当前页面生效wxss仅支持部分的css选择器.class #idelement并集选择器、后代选择器::after ::before等伪类选择器1.4 js逻辑交互通过js文件来处理用户的操作，比如响应用户的点击、获取用户的id等1.4.1 小程序中js文件app.js：整个小程序的入口文件，通过调用App()函数来启动整个小程序。页面的.js:页面的入口文件，通过调用Page()函数来创建并运行页面。普通的.js文件：普通的功能模块文件，用来封装公共的函数或属性供页面使用。02 宿主环境宿主环境是指程序运行所必须的依赖环境。手机微信是小程序的宿主环境。2.1 小程序宿主环境包含的内容2.1.1 通信模型wxml和wxss是渲染层js是逻辑层2.1.2 运行机制小程序启动的过程：把小程序的代码包下载到本地解析app.json全局配置文件执行app.js小程序入口文件，调用App()创建小程序实例渲染小程序首页小程序启动完成页面渲染的过程加载解析页面的json配置文件加载页面的wxml和wxss执行页面的js文件，调用Page()创建页面实例页面渲染完成

牛客数据库SQL实战 51-60（substr切割字符串、group_concat组拼接、limit_offset分页、exists条件成立判断、case分支、表的复用）
type: item
date: 2020-05-14T10:59:23+08:00
description: 51* 获取Employees中的first_name51.1 题目描述获取Employees中的first_name，查询按照first_name最后两个字母，按照升序进行排列CREATE TABLE `employees` ( `emp_no` int(11) NOT NULL, `birth_date` date NOT NULL, `first_name` varchar(14) NOT NULL, `last_name` varchar(16) NOT NULL, `gender` char(1) NOT NULL, `hire_date` date NOT NULL, PRIMARY KEY (`emp_no`));输出格式：first_nameChirstianTzvetanBezalelDuangkaewGeorgiKyoichiAnnekeSumantMaryPartoSaniya51.2 题解 substrselect first_name from employees order by substr(first_name, length(first_name)-1,length(first_name))本题考查 substr(X,Y,Z) 或substr(X,Y)函数的使用。其中X是要截取的字符串。Y是字符串的起始位置==（注意第一个字符的位置为1，而不为0）==，取值范围是±(1~length(X))，当Y等于length(X)时，则截取最后一个字符；当Y等于负整数-n时，则从倒数第n个字符处截取。Z是要截取字符串的长度，取值范围是正整数，若Z省略，则从Y处一直截取到字符串末尾；若Z大于剩下的字符串长度，也是截取到字符串末尾为止。52 按照dept_no进行汇总52.1 题目描述按照dept_no进行汇总，属于同一个部门的emp_no按照逗号进行连接，结果给出dept_no以及连接出的结果employeesCREATE TABLE `dept_emp` ( `emp_no` int(11) NOT NULL, `dept_no` char(4) NOT NULL, `from_date` date NOT NULL, `to_date` date NOT NULL, PRIMARY KEY (`emp_no`,`dept_no`));输出格式:dept_noemployeesd00110001,10002d00210006d00310005d00410003,10004d00510007,10008,10010d00610009,1001052.2 题解 group_concat(字段名,分隔符)select dept_no ,group_concat(emp_no, ",") from dept_emp group by dept_no本题要用到SQLite的聚合函数group_concat(X,Y)，其中X是要连接的字段，Y是连接时用的符号，可省略，默认为逗号。此函数==必须与 GROUP BY 配合使用==。此题以 dept_no 作为分组，将每个分组中不同的emp_no用逗号连接起来（即可省略Y）。53 查找排除当前最大、最小salary之后的员工的平均工资avg_salary53.1 题目描述查找排除当前最大、最小salary之后的员工的平均工资avg_salary。CREATE TABLE `salaries` ( `emp_no` int(11) NOT NULL, `salary` int(11) NOT NULL, `from_date` date NOT NULL, `to_date` date NOT NULL, PRIMARY KEY (`emp_no`,`from_date`));输出格式:avg_salary69462.555555555653.2 题解正常逻辑，OJ过不了select avg(salary) as avg_salary from salaries where salary not in( -- 1 找到最高工资和最小工资的salary (select max(salary) from salaries where to_date = '9999-01-01') -- OJ中需要把时间条件删除，才能过 ,(select min(salary) from salaries where to_date = '9999-01-01') -- OJ中需要把时间条件删除，才能过 ) and to_date = '9999-01-01' OJ通过题解select avg(salary) as avg_salary from salaries where salary no…

牛客数据库SQL实战 41-50（数据替换replace(字段,oldval,newval)、添加主键、获取两表交集intersect、获取字符串长度length(str)）
type: item
date: 2020-05-13T10:00:02+08:00
description: 41 删除emp_no重复的记录，只保留最小的id对应的记录41.1 题目描述删除emp_no重复的记录，只保留最小的id对应的记录。CREATE TABLE IF NOT EXISTS titles_test ( id int(11) not null primary key, emp_no int(11) NOT NULL, title varchar(50) NOT NULL, from_date date NOT NULL, to_date date DEFAULT NULL); insert into titles_test values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('2', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('6', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01');41.2 题解-- 2 删除不在最小id里的数据 delete from titles_test where id not in ( -- 1 先对emp_no进行分组，找到每组的最小id select min(id) id from titles_test group by emp_no)先用 GROUP BY 和 MIN() 选出每个 emp_no 分组中最小的 id，然后用 DELETE FROM ... WHERE ... NOT IN ... 语句删除 “非每个分组最小id对应的所有记录”42 将所有to_date为9999-01-01的全部更新为NULL42.1 题目描述将所有to_date为9999-01-01的全部更新为NULL,且 from_date更新为2001-01-01。CREATE TABLE IF NOT EXISTS titles_test ( id int(11) not null primary key, emp_no int(11) NOT NULL, title varchar(50) NOT NULL, from_date date NOT NULL, to_date date DEFAULT NULL); insert into titles_test values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('2', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'), ('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), ('6', '10002', 'Staff', '1996-08-03', '9999-01-01'), ('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01');42.2 题解update titles_test set to_date = null ,from_date = '2001-01-01' where to_date = '9999-01-01'43* 将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=1000543.1 题目描述将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005,其他数据保持不变，使用replace实现。CREATE TABLE IF NOT EXISTS titles_test ( id int(11) not null primary key, emp_no int(11) NOT NULL…