精华内容
下载资源
问答
  • 2022-03-12 16:03:41

    目录

    点外卖引发的思考

    背景

    First Blood

    double kill

    Triple kill

    为什么要模型

    建模方法论哪家强

    Inmon

    Kimball

    总结

    点外卖引发的思考

    背景

    作为一名宅男,放假在家最开心的时候是什么?当然是点外卖了。打开外卖app的一瞬间,所有吃的都是我的,可以任意挑选,像北京的呷哺呷哺火锅啊,杭州的鲁员外地锅鸡都是不错的选择,在家吃真的太爽了。

    额,咳咳~说到吃的一时间有点把持不住了,我点个外卖先。

    看上面三个图,有木有想立马下单的冲动。忍住,毕竟今天我们要聊的不是怎么吃,而是怎么建模。那我就先开吃了~.~

    大家都知道,外卖的核心业务过程是访问首页-进店-商品详情页-下单,那么如果我们想做外卖的数据建模,我们该如何下手呢?

    First Blood

    大家还记得业务库的ER建模吗?如果没有做过java web,直接做数仓的同学可能比较陌生,但其实了解了ER建模,才能做好数仓建模,而了解ER建模的第一步就是了解业务,其实这个和我们现在常说的业务过程是一致的。

    那么点外卖这个过程都有哪些角色的参与?这些角色都做了什么?产生了什么样的结果呢?

    1. 角色

      1. 消费者,就是点外卖的我们,也可以尊称为妄图通过各种优惠券薅平台羊毛的小韭菜;

      2. 商家,妄图通过平台的流量薅消费者羊毛的卖家;

      3. 平台,庄家,通吃。

    1. 行为

      1. 商家申请入住平台;

      2. 消费者在平台逛街;

      3. 消费者进店下单。

    1. 结果

      1. 商家开店产生了供应链和商品的动销;

      2. 用户浏览产生了用户行为日志;

      3. 用户下单产生了订单;

      4. 下单之后产生了配送,以及咨询等等。

    double kill

    上面的角色、行为、结果就形成了一些ER模型,举例如下:

    消费者购买商品的ER模型

    对应数据库设计如下(一般订单表会存在两个)

    Triple kill

    业务系统构建的ER模型目的是什么?当然是为了实现业务功能。

    他关心数据的统计分析吗?他不关心。

    那我们作为面向分析的数据建模可以完全使用ER建模吗?必须不行啊。

    那数据建模怎么jian?我们可以借鉴ER模型啊。

    为什么要模型

    业务库的ER建模是为了实现业务功能而产生的一种设计方式,那么我们数据建模是为了什么?还记得数据仓库的特征吗?

    数据仓库特征

    so what?我们来挨个分析一下子

    面向主题,主题是数据的分析边界。啥是数据的分析边界?就是根据行业特性总结出来的一套数据的划分。好像懂了,但是并没有完全懂。不懂没关系,咱们就先认为这个就是通过一种数据分类,让统计分析更加的方便。

    数据是集成的。这个好理解,把所有的东西都放在一起就是集成。没毛病,也就是说,数仓就像一个数据中心,是可以接受所有的业务数据,除了非结构化数据。哦。我明白了,怪不得说数仓是面向企业级别的,如果再看第一条的话,那是不是这个主题域是不分业务系统的?完全正确。

    据仓库中的数据反映历史变化。怎么才能反应历史变化呢?我记得业务系统都是一直update的,除非数仓能把所有的历史数据都保存下来。

    数据仓库中的数据是稳定的(或称不可修改的)。这个不太好理解,啥叫稳定的。大家查询业务系统的时候是不是只能看到最新状态的数据,如果想看已经被覆盖或者更新的操作记录是不是就看不到了,那这怎么办,我们做数据分析的时候,如果一个指标口径算错了,想重新计算一下某个时间点的值,业务系统算的出来吗?他算不出来,数仓可以算出来吗?必须可以啊。

    也就是说我们数据建模的目的是为了更好的实现企业数据统计分析的能力

    建模方法论哪家强

    说起数据建模,那首先想到的就是鼻祖Inmon啊,为啥?数据仓库的概念就是老人家提出来的啊,但是现在大家身边用Inmon建模的多吗?几乎没有了,这是为啥?为什么Kimball变成了后起之秀。听我给大家辩解。

    Inmon

    Inmon模型是Bill Inmon老爷子提出来的,他的设计思路是:自上向下的(数据流向),也就是从数据源->数仓->数据集市,设计步骤如下:

      • 业务系统数据通过ETL过程入仓;

      • 数仓满足第三范式的;

      • 数据集市按照主题划分。

    我们可以看到,Inmon的数据仓库是通过将所有业务数据入仓并且构建满足第三范式的数据模型,也就是说他和ER模型比较接近,是规范化的,那么为什么规范化的数仓最终没有被普遍使用呢?

    其次,Inmon的数据集市是独立与数据仓库以外的,所以需要把分主题的数据再通过一次ETL过程导入到数据集市中。

    我们再接着看一看Kimball是个啥

    Kimball

    Kimball是Ralph Kimbal大神提出的,也被称为维度建模。维度建模的模型是自底向上的,即从数据集市-> 数据仓库 -> 数据源。设计步骤如下

      • 分析最终任务,将数据按照目标拆分出不同的表需求,形成数据集市层;

      • 为了得到实现最终任务的结果表,需要构建数据仓库层,由事实表和维度表构成;

      • 将需要的数据通过ETL工具入仓。

    维度建模是通过结果来构建数仓的,所以并不需要将所有业务数据入仓,上手难度较低,这个大家最喜欢了;

    数据仓库层用了一种新的划分方式:维度、事实,这俩是什么东西?

    数据集市没有了?其实数据集市合并到了数据仓库里面。

    总结

    我们从生活中的一次点外卖,一步一步的分析业务系统的ER模型设计,再到数据建模的Inmon和Kimball。我们可以看的出来,业务系统建模是针对业务功能的,而数据建模是为了针对数据的统计分析的

    Inmon和Kimball各有各自的特点,但是之所以Kimball被众多互联网公司选择,最重要的原因是他的设计比较简单,Kimball完全是结果驱动,可以快速拿到结果,但是Inmon因为需要构建一个完整的企业级数据仓库,前期需要花费大量的时间和经历来设计,有这个时间,说不定业务都没了,谁还看你的统计结果。

    但是Inmon的设计里面把数据集市独立于数仓之外的设计被借鉴了下来,我们现有的数据仓库架构中,大部分都是用一个或者多个olap作为数据集市,不过多个olap虽然解决了不同应用场景,但是形成了数据孤岛,所以大势所趋是统一数据集市的存储。

    其次,Kimball的设计因为是结果导向,并且本身维度建模就会出现数据冗余,所以会出现大量的数据质量问题烟囱式开发的问题,导致当下大家能看到漫天飞的数据治理场景,这就是选择使用Kimball的后遗症。

    那么之后的Onedata在Kimball的基础上做了哪些优化呢?维度建模如何落地呢?事实、维度又是是什么东西呢?建模过程的大宽表、分层又是如何做的呢?且听村长下回分解。

    关注博主不迷路~

    更多相关内容
  • 外卖外卖省省外卖探探美团饿了么外卖联盟优惠券小程序系统软件开发源码 美团/饿了么外卖CPS联盟返利公众号小程序裂变核心源码 饿了么、美团优惠开发(外卖cps,三级裂变源码) 源码下载/搭建 http://y.mybei.cn 截图 ...

    外卖CPS小程序源码分享

    外卖券外卖省省外卖探探美团饿了么外卖联盟优惠券小程序系统软件开发源码 美团/饿了么外卖CPS联盟返利公众号小程序裂变核心源码

    饿了么、美团优惠开发(外卖cps,三级裂变源码)

    源码下载/搭建

    http://y.mybei.cn

    截图

    在这里插入图片描述
    在这里插入图片描述

    功能列表

    • 特价电影票

    • 饿了么外卖(3个红包)

    • 美团外卖

    • 美团优选(1分钱买菜)

    • 购物返利(淘宝,拼多多,京东)

    • 话费优惠充值(92折,慢充)

    • 火车票优惠

    • 滴滴打车优惠

    • 小程序广告收益(流量主)

    • 公众号绑定

    • 更多功能…

    作者联系方式

    • 交流交流感情也好呀~

    • 代搭建,源码都可以出,好谈~

    • 转介绍,代理,都行,作者不会亏待你~

    步骤

    • 下载以上源代码到本地

    http://y.mybei.cn

    没用的代码, 请忽略

    前言
    知识无底,学海无涯,到今天进入MySQL的学习4天了,知识点虽然简单,但是比较多,所以写一篇博客将MySQL的基础写出来,方便自己以后查找,还有就是分享给大家。

    一、SQL简述
    1.SQL的概述
    Structure Query Language(结构化查询语言)简称SQL,它被美国国家标准局(ANSI)确定为关系型数据库语言的美国标准,后被国际化标准组织(ISO)采纳为关系数据库语言的国际标准。数据库管理系统可以通过SQL管理数据库;定义和操作数据,维护数据的完整性和安全性。

    2.SQL的优点
    1、简单易学,具有很强的操作性
    2、绝大多数重要的数据库管理系统均支持SQL
    3、高度非过程化;用SQL操作数据库时大部分的工作由DBMS自动完成

    3.SQL的分类
    1、DDL(Data Definition Language) 数据定义语言,用来操作数据库、表、列等; 常用语句:CREATE、 ALTER、DROP
    2、DML(Data Manipulation Language) 数据操作语言,用来操作数据库中表里的数据;常用语句:INSERT、 UPDATE、 DELETE
    3、DCL(Data Control Language) 数据控制语言,用来操作访问权限和安全级别; 常用语句:GRANT、DENY
    4、DQL(Data Query Language) 数据查询语言,用来查询数据 常用语句:SELECT

    二、数据库的三大范式
    1、第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据线;也就是说:每列的值具有原子性,不可再分割。
    2、第二范式(2NF)是在第一范式(1NF)的基础上建立起来得,满足第二范式(2NF)必须先满足第一范式(1NF)。如果表是单主键,那么主键以外的列必须完全依赖于主键;如果表是复合主键,那么主键以外的列必须完全依赖于主键,不能仅依赖主键的一部分。
    3、第三范式(3NF)是在第二范式的基础上建立起来的,即满足第三范式必须要先满足第二范式。第三范式(3NF)要求:表中的非主键列必须和主键直接相关而不能间接相关;也就是说:非主键列之间不能相关依赖。

    三、数据库的数据类型
    使用MySQL数据库存储数据时,不同的数据类型决定了 MySQL存储数据方式的不同。为此,MySQL数据库提供了多种数据类型,其中包括整数类型、浮点数类型、定点 数类型、日期和时间类型、字符串类型、二进制…等等数据类型。

    1.整数类型
    根据数值取值范围的不同MySQL 中的整数类型可分为5种,分别是TINYINT、SMALUNT、MEDIUMINT、INT和 BIGINT。下图列举了 MySQL不同整数类型所对应的字节大小和取值范围而最常用的为INT类型的,

    数据类型 字节数 无符号数的取值范围 有符号数的取值范围
    TINYINT 1 0~255 -128~127
    SMALLINT 2 0~65535 -32768~32768
    MEDIUMINT 3 0~16777215 -8388608~8388608
    INT 4 0~4294967295 -2147483648~ 2147483648
    BIGINT 8 0~18446744073709551615 -9223372036854775808~9223372036854775808
    2.浮点数类型和定点数类型
    在MySQL数据库中使用浮点数和定点数来存储小数。浮点数的类型有两种:单精度浮点数类型(FLOAT)和双精度浮点数类型(DOUBLE)。而定点数类型只有一种即DECIMAL类型。下图列举了 MySQL中浮点数和定点数类型所对应的字节大小及其取值范围:

    数据类型 字节数 有符号的取值范围 无符号的取值范围
    FLOAT 4 -3.402823466E+38~-1.175494351E-38 0和1.175494351E-38~3.402823466E+38
    DOUBLE 8 -1.7976931348623157E+308~2.2250738585072014E-308 0和2.2250738585072014E-308~1.7976931348623157E+308
    DECIMAL(M,D) M+2 -1.7976931348623157E+308~2.2250738585072014E-308 0和2.2250738585072014E-308~1.7976931348623157E+308
    从上图中可以看出:DECIMAL类型的取值范围与DOUBLE类型相同。但是,请注意:DECIMAL类型的有效取值范围是由M和D决定的。其中,M表示的是数据的长 度,D表示的是小数点后的长度。比如,将数据类型为DECIMAL(6,2)的数据6.5243 插人数据库后显示的结果为6.52

    3.字符串类型
    在MySQL中常用CHAR 和 VARCHAR 表示字符串。两者不同的是:VARCHAR存储可变长度的字符串。
    当数据为CHAR(M)类型时,不管插入值的长度是实际是多少它所占用的存储空间都是M个字节;而VARCHAR(M)所对应的数据所占用的字节数为实际长度加1

    插入值 CHAR(3) 存储需求 VARCHAR(3) 存储需求
    ‘’ ‘’ 3个字节 ‘’ 1个字节
    ‘a’ ‘a’ 3个字节 ‘a’ 2个字节
    ‘ab’ ‘ab’ 3个字节 ‘ab’ 3个字节
    ‘abc’ ‘ab’ 3个字节 ‘abc’ 4个字节
    ‘abcd’ ‘ab’ 3个字节 ‘abc’ 4字节
    4.字符串类型
    文本类型用于表示大文本数据,例如,文章内容、评论、详情等,它的类型分为如下4种:

    数据类型 储存范围
    TINYTEXT 0~255字节
    TEXT 0~65535字节
    MEDIUMTEXT 0~16777215字节
    LONGTEXT 0~4294967295字节
    5.日期与时间类型
    MySQL提供的表示日期和时间的数据类型分别是 :YEAR、DATE、TIME、DATETIME 和 TIMESTAMP。下图列举了日期和时间数据类型所对应的字节数、取值范围、日期格式以及零值:

    数据类型 字节数 取值范围 日期格式 零值
    YEAR 1 1901~2155 YYYY 0000
    DATE 4 1000-01-01~9999-12-31 YYYY-MM-DD 0000-00-00
    TIME 3 -838:59:59~ 838:59:59 HH:MM:SS 00:00:00
    DATETIME 8 1000-01-01 00:00:00~9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 0000-00-00 00:00:00
    TIMESTAMP 4 1970-01-01 00:00:01~2038-01-19 03:14:07 YYYY-MM-DD HH:MM:SS 0000-00-00 00:00:00
    5.1 YEAR类型
    YEAR类型用于表示年份,在MySQL中,可以使用以下三种格式指定YEAR类型 的值。
    1、使用4位字符串或数字表示,范围为’1901’—'2155’或1901—2155。例如,输人 ‘2019’或2019插人到数据库中的值均为2019。
    2、使用两位字符串表示,范围为’00’—‘99’。其中,‘00’—'69’范围的值会被转换为 2000—2069范围的YEAR值,‘70’—'99’范围的值会被转换为1970—1999范围的YEAR 值。例如,输人’19’插人到数据库中的值为2019。
    3、使用两位数字表示,范围为1—99。其中,1—69范围的值会被转换为2001— 2069范围的YEAR值,70—99范围的值会被转换为1970—1999范围的YEAR值。例 如,输人19插入到数据库中的值为2019。
    请注意:当使用YEAR类型时,一定要区分’0’和0。因为字符串格式的’0’表示的YEAR值是2000而数字格式的0表示的YEAR值是0000。

    5.2 TIME类型
    TIME类型用于表示时间值,它的显示形式一般为HH:MM:SS,其中,HH表示小时, MM表示分,SS表示秒。在MySQL中,可以使用以下3种格式指定TIME类型的值。
    1、以’D HH:MM:SS’字符串格式表示。其中,D表示日可取0—34之间的值, 插人数据时,小时的值等于(DX24+HH)。例如,输入’2 11:30:50’插人数据库中的日期为59:30:50。
    2、以’HHMMSS’字符串格式或者HHMMSS数字格式表示。 例如,输人’115454’或115454,插入数据库中的日期为11:54:54
    3、使用CURRENT_TIME或NOW()输人当前系统时间。

    5.3 DATETIME类型
    DATETIME类型用于表示日期和时间,它的显示形式为’YYYY-MM-DD HH: MM:SS’,其中,YYYY表示年,MM表示月,DD表示日,HH表示小时,MM表示分,SS 表示秒。在MySQL中,可以使用以下4种格式指定DATETIME类型的值。
    以’YYYY-MM-DD HH:MM:SS’或者’YYYYMMDDHHMMSS’字符串格式表示的日期和时间,取值范围为’1000-01-01 00:00:00’—‘9999-12-3 23:59:59’。例如,输人’2019-01-22 09:01:23’或 ‘20140122_0_90123’插人数据库中的 DATETIME 值都为 2019-01-22 09:01:23。
    1、以’YY-MM-DD HH:MM:SS’或者’YYMMDDHHMMSS’字符串格式表示的日期和时间,其中YY表示年,取值范围为’00’—‘99’。与DATE类型中的YY相同,‘00’— '69’范围的值会被转换为2000—2069范围的值,‘70’—'99’范围的值会被转换为1970—1999范围的值。
    2、以YYYYMMDDHHMMSS或者YYMMDDHHMMSS数字格式表示的日期 和时间。例如,插入20190122090123或者190122090123,插人数据库中的DATETIME值都 为 2019-01-22 09:01:23。
    3、使用NOW来输人当前系统的日期和时间。

    5.4 TIMESTAMP类型
    TIMESTAMP类型用于表示日期和时间,它的显示形式与DATETIME相同但取值范围比DATETIME小。在此,介绍几种TIMESTAMP类型与DATATIME类型不同的形式:
    1、使用CURRENT_TIMESTAMP输人系统当前日期和时间。
    2、输人NULL时系统会输人系统当前日期和时间。
    3、无任何输人时系统会输入系统当前日期和时间。

    6.二进制类型
    在MySQL中常用BLOB存储二进制类型的数据,例如:图片、PDF文档等。BLOB类型分为如下四种:

    数据类型 储存范围
    TINYBLOB 0~255字节
    BLOB 0~65535字节
    MEDIUMBLOB 0~16777215字节
    LONGBLOB 0~4294967295字节
    四、数据库、数据表的基本操作
    1.数据库的基本操作
    MySQL安装完成后,要想将数据存储到数据库的表中,首先要创建一个数据库。创 建数据库就是在数据库系统中划分一块空间存储数据,语法如下:

    create database 数据库名称;
    1
    创建一个叫db1的数据库MySQL命令:

    – 创建一个叫db1的数据库
    show create database db1;
    1
    2
    运行效果展示:

    创建数据库后查看该数据库基本信息MySQL命令:

    show create database db1;
    1
    运行效果展示:

    删除数据库MySQL命令:

    drop database db1;
    1
    运行效果展示:

    查询出MySQL中所有的数据库MySQL命令:

    show databases;
    1
    运行效果展示:

    将数据库的字符集修改为gbk MySQL命令:

    alter database db1 character set gbk;
    1
    运行效果展示:

    切换数据库 MySQL命令:

    use db1;
    1
    运行效果展示:

    查看当前使用的数据库 MySQL命令:

    select database();
    1
    运行效果展示:

    2.数据表的基本操作
    数据库创建成功后可在该数据库中创建数据表(简称为表)存储数据。请注意:在操作数据表之前应使用“USE 数据库名;”指定操作是在哪个数据库中进行先关操作,否则会抛出“No database selected”错误。
    语法如下:

    create table 表名(
    字段1 字段类型,
    字段2 字段类型,

    字段n 字段类型
    );
    1
    2
    3
    4
    5
    6
    2.1 创建数据表
    示例:创建学生表 MySQL命令:

    create table student(
    id int,
    name varchar(20),
    gender varchar(10),
    birthday date
    );
    1
    2
    3
    4
    5
    6
    运行效果展示:

    2.2 查看数据表
    示例:查看当前数据库中所有表 MySQL命令:

    show tables;
    1
    运行效果展示:

    示例:查表的基本信息 MySQL命令:

    show create table student;
    1
    运行效果展示:

    示例:查看表的字段信息 MySQL命令:

    desc student;
    1
    运行效果展示:

    2.3 修改数据表
    有时,希望对表中的某些信息进行修改,例如:修改表名、修改字段名、修改字段 数据类型…等等。在MySQL中使用alter table修改数据表.
    示例:修改表名 MySQL命令:

    alter table student rename to stu;
    1
    运行效果展示:

    示例:修改字段名 MySQL命令:

    alter table stu change name sname varchar(10);
    1
    运行效果展示:

    示例:修改字段数据类型 MySQL命令:

    alter table stu modify sname int;
    1
    运行效果展示:

    示例:增加字段 MySQL命令:

    alter table stu add address varchar(50);
    1
    运行效果展示:

    示例:删除字段 MySQL命令:

    alter table stu drop address;
    1
    运行效果展示:

    2.4 删除数据表
    语法:

    drop table 表名;
    1
    示例:删除数据表 MySQL命令:

    drop table stu;
    1
    运行效果展示:

    五、数据表的约束
    为防止错误的数据被插入到数据表,MySQL中定义了一些维护数据库完整性的规则;这些规则常称为表的约束。常见约束如下:

    约束条件 说明
    PRIMARY KEY 主键约束用于唯一标识对应的记录
    FOREIGN KEY 外键约束
    NOT NULL 非空约束
    UNIQUE 唯一性约束
    DEFAULT 默认值约束,用于设置字段的默认值
    以上五种约束条件针对表中字段进行限制从而保证数据表中数据的正确性和唯一性。换句话说,表的约束实际上就是表中数据的限制条件。

    1.主键约束
    主键约束即primary key用于唯一的标识表中的每一行。被标识为主键的数据在表中是唯一的且其值不能为空。这点类似于我们每个人都有一个身份证号,并且这个身份证号是唯一的。
    主键约束基本语法:

    字段名 数据类型 primary key;
    1
    设置主键约束(primary key)的第一种方式
    示例:MySQL命令:

    create table student(
    id int primary key,
    name varchar(20)
    );
    1
    2
    3
    4
    运行效果展示:

    设置主键约束(primary key)的第二·种方式
    示例:MySQL命令:

    create table student01(
    id int
    name varchar(20),
    primary key(id)
    );
    1
    2
    3
    4
    5
    运行效果展示:

    2.非空约束
    非空约束即 NOT NULL指的是字段的值不能为空,基本的语法格式如下所示:

    字段名 数据类型 NOT NULL;
    1
    示例:MySQL命令:

    create table student02(
    id int
    name varchar(20) not null
    );
    1
    2
    3
    4
    运行效果展示:

    3.默认值约束
    默认值约束即DEFAULT用于给数据表中的字段指定默认值,即当在表中插入一条新记录时若未给该字段赋值,那么,数据库系统会自动为这个字段插人默认值;其基本的语法格式如下所示:

    字段名 数据类型 DEFAULT 默认值;
    1
    示例:MySQL命令:

    create table student03(
    id int,
    name varchar(20),
    gender varchar(10) default ‘male’
    );
    1
    2
    3
    4
    5
    运行效果展示:

    5.唯一性约束
    唯一性约束即UNIQUE用于保证数据表中字段的唯一性,即表中字段的值不能重复出现,其基本的语法格式如下所示:

    字段名 数据类型 UNIQUE;
    1
    示例:MySQL命令:

    create table student04(
    id int,
    name varchar(20) unique
    );
    1
    2
    3
    4
    运行效果展示:

    6.外键约束
    外键约束即FOREIGN KEY常用于多张表之间的约束。基本语法如下:

    – 在创建数据表时语法如下:
    CONSTRAINT 外键名 FOREIGN KEY (从表外键字段) REFERENCES 主表 (主键字段)
    – 将创建数据表创号后语法如下:
    ALTER TABLE 从表名 ADD CONSTRAINT 外键名 FOREIGN KEY (从表外键字段) REFERENCES 主表 (主键字段);
    1
    2
    3
    4
    示例:创建一个学生表 MySQL命令:

    create table student05(
    id int primary key,
    name varchar(20)
    );
    1
    2
    3
    4
    示例:创建一个班级表 MySQL命令:

    create table class(
    classid int primary key,
    studentid int
    );
    1
    2
    3
    4
    示例:学生表作为主表,班级表作为副表设置外键, MySQL命令:

    alter table class add constraint fk_class_studentid foreign key(studentid) references student05(id);
    1
    运行效果展示:

    6.1 数据一致性概念
    大家知道:建立外键是为了保证数据的完整和统一性。但是,如果主表中的数据被删除或修改从表中对应的数据该怎么办呢?很明显,从表中对应的数据也应该被删除,否则数据库中会存在很多无意义的垃圾数据。

    6.2 删除外键
    语法如下:

    alter table 从表名 drop foreign key 外键名;
    1
    示例:删除外键 MySQL命令:

    alter table class drop foreign key fk_class_studentid;
    1
    运行效果展示:

    外键的那个字段不在了证明删除成功了

    6.3 关于外键约束需要注意的细节
    1、从表里的外键通常为主表的主键
    2、从表里外键的数据类型必须与主表中主键的数据类型一致
    3、主表发生变化时应注意主表与从表的数据一致性问题

    六、数据表插入数据
    在MySQL通过INSERT语句向数据表中插入数据。在此,我们先准备一张学生表,代码如下:

    create table student(
    id int,
    name varchar(30),
    age int,
    gender varchar(30)
    );
    1
    2
    3
    4
    5
    6

    1. 为表中所有字段插入数据
      每个字段与其值是严格一一对应的。也就是说:每个值、值的顺序、值的类型必须与对应的字段相匹配。但是,各字段也无须与其在表中定义的顺序一致,它们只要与 VALUES中值的顺序一致即可。
      语法如下:

    INSERT INTO 表名(字段名1,字段名2,…) VALUES (值 1,值 2,…);
    1
    示例:向学生表中插入一条学生信息 MySQL命令:

    insert into student (id,name,age,gender) values (1,‘bob’,16,‘male’);
    1
    运行效果展示:

    1. 为表中指定字段插入数据
      语法如下:

    INSERT INTO 表名(字段名1,字段名2,…) VALUES (值 1,值 2,…);
    1
    插入数据的方法基本和为表中所有字段插入数据,一样,只是需要插入的字段由你自己指定

    1. 同时插入多条记录
      语法如下:

    INSERT INTO 表名 [(字段名1,字段名2,…)]VALUES (值 1,值 2,…),(值 1,值 2,…),…;
    1
    在该方式中:(字段名1,字段名2,…)是可选的,它用于指定插人的字段名;(值 1,值 2,…),(值 1,值 2,…)表示要插人的记录,该记录可有多条并且每条记录之间用逗号隔开。
    示例:向学生表中插入多条学生信息 MySQL命令:

    insert into student (id,name,age,gender) values (2,‘lucy’,17,‘female’),(3,‘jack’,19,‘male’),(4,‘tom’,18,‘male’);
    1
    运行效果展示:

    七、更新数据
    在MySQL通过UPDATE语句更新数据表中的数据。在此,我们将就用六中的student学生表

    1. UPDATE基本语法
      UPDATE 表名 SET 字段名1=值1[,字段名2 =值2,…] [WHERE 条件表达式];
      1
      在该语法中:字段名1、字段名2…用于指定要更新的字段名称;值1、值 2…用于表示字段的新数据;WHERE 条件表达式 是可选的,它用于指定更新数据需要满足的条件

    2. UPDATE更新部分数据
      示例:将name为tom的记录的age设置为20并将其gender设置为female MySQL命令:

    update student set age=20,gender=‘female’ where name=‘tom’;
    1
    运行效果展示:

    1. UPDATE更新全部数据
      示例:将所有记录的age设置为18 MySQL命令:

    update student set age=18;
    1
    运行效果展示:

    八、删除数据
    在MySQL通过DELETE语句删除数据表中的数据。在此,我们先准备一张数据表,代码如下:

    – 创建学生表
    create table student(
    id int,
    name varchar(30),
    age int,
    gender varchar(30)
    );
    – 插入数据
    insert into student (id,name,age,gender) values (2,‘lucy’,17,‘female’),(3,‘jack’,19,‘male’),(4,‘tom’,18,‘male’),(5,‘sal’,19,‘female’),(6,‘sun’,20,‘male’)
    ,(7,‘sad’,13,‘female’),(8,‘sam’,14,‘male’);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    1. DELETE基本语法
      在该语法中:表名用于指定要执行删除操作的表;[WHERE 条件表达式]为可选参数用于指定删除的条件。

    DELETE FROM 表名 [WHERE 条件表达式];
    1
    2. DELETE删除部分数据
    示例:删除age等于14的所有记录 MySQL命令:

    delete from student where age=14;
    1
    运行效果展示:

    1. DELETE删除全部数据
      示例:删除student表中的所有记录 MySQL命令:

    delete from student;
    1
    运行效果展示:

    1. TRUNCATE和DETELE的区别
      TRUNCATE和DETELE都能实现删除表中的所有数据的功能,但两者也是有区别的:
      1、DELETE语句后可跟WHERE子句,可通过指定WHERE子句中的条件表达式只删除满足条件的部分记录;但是,TRUNCATE语句只能用于删除表中的所有记录。
      2、使用TRUNCATE语句删除表中的数据后,再次向表中添加记录时自动增加字段的默认初始值重新由1开始;使用DELETE语句删除表中所有记录后,再次向表中添加记录时自动增加字段的值为删除时该字段的最大值加1
      3、DELETE语句是DML语句,TRUNCATE语句通常被认为是DDL语句

    九、MySQL数据表简单查询
    1.简单查询概述
    简单查询即不含where的select语句。在此,我们讲解简单查询中最常用的两种查询:查询所有字段和查询指定字段。
    在此,先准备测试数据,代码如下:

    – 创建数据库
    DROP DATABASE IF EXISTS mydb;
    CREATE DATABASE mydb;
    USE mydb;

    – 创建student表
    CREATE TABLE student (
    sid CHAR(6),
    sname VARCHAR(50),
    age INT,
    gender VARCHAR(50) DEFAULT ‘male’
    );

    – 向student表插入数据
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1001’, ‘lili’, 14, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1002’, ‘wang’, 15, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1003’, ‘tywd’, 16, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1004’, ‘hfgs’, 17, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1005’, ‘qwer’, 18, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1006’, ‘zxsd’, 19, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1007’, ‘hjop’, 16, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1008’, ‘tyop’, 15, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1009’, ‘nhmk’, 13, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1010’, ‘xdfv’, 17, ‘female’);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    2.查询所有字段(方法不唯一只是举例)
    查询所有字段 MySQL命令:

    select * from student;
    1
    运行效果展示:

    3.查询指定字段(sid、sname)
    查询指定字段(sid、sname) MySQL命令:

    select sid,sname from student;
    1
    运行效果展示:

    4.常数的查询
    在SELECT中除了书写列名,还可以书写常数。可以用于标记
    常数的查询日期标记 MySQL命令:

    select sid,sname,‘2021-03-02’ from student;
    1
    运行效果展示:

    5.从查询结果中过滤重复数据
    在使用DISTINCT 时需要注意:
    在SELECT查询语句中DISTINCT关键字只能用在第一个所查列名之前。
    MySQL命令:

    select distinct gender from student;
    1
    运行效果展示:

    6.算术运算符(举例加运算符)
    在SELECT查询语句中还可以使用加减乘除运算符。
    查询学生10年后的年龄 MySQL命令:

    select sname,age+10 from student;
    1
    运行效果展示:

    十、函数
    在此,先准备测试数据,代码如下:

    – 创建数据库
    DROP DATABASE IF EXISTS mydb;
    CREATE DATABASE mydb;
    USE mydb;

    – 创建student表
    CREATE TABLE student (
    sid CHAR(6),
    sname VARCHAR(50),
    age INT,
    gender VARCHAR(50) DEFAULT ‘male’
    );

    – 向student表插入数据
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1001’, ‘lili’, 14, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1002’, ‘wang’, 15, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1003’, ‘tywd’, 16, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1004’, ‘hfgs’, 17, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1005’, ‘qwer’, 18, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1006’, ‘zxsd’, 19, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1007’, ‘hjop’, 16, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1008’, ‘tyop’, 15, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1009’, ‘nhmk’, 13, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1010’, ‘xdfv’, 17, ‘female’);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    1.聚合函数
    在开发中,我们常常有类似的需求:统计某个字段的最大值、最小值、 平均值等等。为此,MySQL中提供了聚合函数来实现这些功能。所谓聚合,就是将多行汇总成一行;其实,所有的聚合函数均如此——输入多行,输出一行。聚合函数具有自动滤空的功能,若某一个值为NULL,那么会自动将其过滤使其不参与运算。
    聚合函数使用规则:
    只有SELECT子句和HAVING子句、ORDER BY子句中能够使用聚合函数。例如,在WHERE子句中使用聚合函数是错误的。
    接下来,我们学习常用聚合函数。

    1.1、count()
    统计表中数据的行数或者统计指定列其值不为NULL的数据个数
    查询有多少该表中有多少人
    MySQL命令:

    select count(*) from student;
    1
    运行效果展示:

    1.2、max()
    计算指定列的最大值,如果指定列是字符串类型则使用字符串排序运算

    查询该学生表中年纪最大的学生
    MySQL命令:

    select max(age) from student;
    1
    运行效果展示:

    1.3、min()
    计算指定列的最小值,如果指定列是字符串类型则使用字符串排序运算

    查询该学生表中年纪最小的学生 MySQL命令:

    select sname,min(age) from student;
    1
    运行效果展示:

    1.4、sum()
    计算指定列的数值和,如果指定列类型不是数值类型则计算结果为0
    查询该学生表中年纪的总和 MySQL命令:

    select sum(age) from student;
    1
    运行效果展示:

    1.5、avg()
    计算指定列的平均值,如果指定列类型不是数值类型则计算结果为

    查询该学生表中年纪的平均数 MySQL命令:

    select avg(age) from student;
    1
    运行效果展示:

    2.其他常用函数
    这里我就不一一举例了,基本混个眼熟,以后用到再细说

    2.1、时间函数
    SELECT NOW();
    SELECT DAY (NOW());
    SELECT DATE (NOW());
    SELECT TIME (NOW());
    SELECT YEAR (NOW());
    SELECT MONTH (NOW());
    SELECT CURRENT_DATE();
    SELECT CURRENT_TIME();
    SELECT CURRENT_TIMESTAMP();
    SELECT ADDTIME(‘14:23:12’,‘01:02:01’);
    SELECT DATE_ADD(NOW(),INTERVAL 1 DAY);
    SELECT DATE_ADD(NOW(),INTERVAL 1 MONTH);
    SELECT DATE_SUB(NOW(),INTERVAL 1 DAY);
    SELECT DATE_SUB(NOW(),INTERVAL 1 MONTH);
    SELECT DATEDIFF(‘2019-07-22’,‘2019-05-05’);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    2.2、字符串函数
    –连接函数
    SELECT CONCAT ()

    SELECT INSTR ();
    –统计长度
    SELECT LENGTH();
    1
    2
    3
    4
    5
    6
    2.3、数学函数
    – 绝对值
    SELECT ABS(-136);
    – 向下取整
    SELECT FLOOR(3.14);
    – 向上取整
    SELECT CEILING(3.14);
    1
    2
    3
    4
    5
    6
    十一、条件查询
    数据库中存有大量数据,我们可根据需求获取指定的数据。此时,我们可在查询语句中通过WHERE子句指定查询条件对查询结果进行过滤。
    在开始学习条件查询之前,我们先准备测试数据,代码如下:

    – 创建数据库
    DROP DATABASE IF EXISTS mydb;
    CREATE DATABASE mydb;
    USE mydb;

    – 创建student表
    CREATE TABLE student (
    sid CHAR(6),
    sname VARCHAR(50),
    age INT,
    gender VARCHAR(50) DEFAULT ‘male’
    );

    – 向student表插入数据
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1001’, ‘lili’, 14, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1002’, ‘wang’, 15, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1003’, ‘tywd’, 16, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1004’, ‘hfgs’, 17, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1005’, ‘qwer’, 18, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1006’, ‘zxsd’, 19, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1007’, ‘hjop’, 16, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1008’, ‘tyop’, 15, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1009’, ‘nhmk’, 13, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1010’, ‘xdfv’, 17, ‘female’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1012’, ‘lili’, 14, ‘male’);
    INSERT INTO student (sid,sname,age,gender) VALUES (‘S_1013’, ‘wang’, 15, ‘female’);
    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
    1.使用关系运算符查询
    在WHERE中可使用关系运算符进行条件查询,常用的关系运算符如下所示:

    关系运算符 说明
    = 等于
    <> 不等于
    != 不等于
    < 小于
    <= 小于等于

    大于
    = 大于等于
    查询年龄等于或大于17的学生的信息 MySQL命令:

    select * from student where age>=17;
    1
    运行效果展示:

    2.使用IN关键字查询
    IN关键字用于判断某个字段的值是否在指定集合中。如果字段的值恰好在指定的集合中,则将字段所在的记录将査询出来。

    查询sid为S_1002和S_1003的学生信息 MySQL命令:

    select * from student where sid in (‘S_1002’,‘S_1003’);
    1
    运行效果展示:

    查询sid为S_1001以外的学生的信息 MySQL命令:

    select * from student where sid not in (‘S_1001’);
    1
    运行效果展示:

    3.使用BETWEEN AND关键字查询
    BETWEEN AND用于判断某个字段的值是否在指定的范围之内。如果字段的值在指定范围内,则将所在的记录将查询出来
    查询15到18岁的学生信息 MySQL命令:

    select * from student where age between 15 and 18;
    1
    运行效果展示:

    查询不是15到18岁的学生信息 MySQL命令:

    select * from student where age not between 15 and 18;
    1
    运行效果展示:

    4.使用空值查询
    在MySQL中,使用 IS NULL关键字判断字段的值是否为空值。请注意:空值NULL不同于0,也不同于空字符串
    由于student表没有空值就不演示查询空值的了
    查询sname不为空值的学生信息 MySQL命令:

    select * from student where sname is not null;
    1
    运行效果展示:

    5.使用AND关键字查询
    在MySQL中可使用AND关键字可以连接两个或者多个查询条件。
    查询年纪大于15且性别为male的学生信息 MySQL命令:

    select * from student where age>15 and gender=‘male’;
    1
    运行效果展示:

    6.使用OR关键字查询
    在使用SELECT语句查询数据时可使用OR关键字连接多个査询条件。在使用OR关键字时,只要记录满足其中任意一个条件就会被查询出来
    查询年纪大于15或者性别为male的学生信息 MySQL命令:

    select * from student where age>15 or gender=‘male’;
    1
    运行效果展示:

    7.使用LIKE关键字查询
    MySQL中可使用LIKE关键字可以判断两个字符串是否相匹配

    7.1 普通字符串
    查询sname中与wang匹配的学生信息 MySQL命令:

    select * from student where sname like ‘wang’;
    1
    运行效果展示:

    7.2 含有%通配的字符串
    %用于匹配任意长度的字符串。例如,字符串“a%”匹配以字符a开始任意长度的字符串
    查询学生姓名以li开始的记录 MySQL命令:

    select * from student where sname like ‘li%’;
    1
    运行效果展示:

    查询学生姓名以g结尾的记录 MySQL命令:

    select * from student where sname like ‘%g’;
    1
    运行效果展示:

    查询学生姓名包含s的记录 MySQL命令:

    select * from student where sname like ‘%s%’;
    1
    运行效果展示

    7.3 含有_通配的字符串
    下划线通配符只匹配单个字符,如果要匹配多个字符,需要连续使用多个下划线通配符。例如,字符串“ab_”匹配以字符串“ab”开始长度为3的字符串,如abc、abp等等;字符串“a__d”匹配在字符“a”和“d”之间包含两个字符的字符串,如"abcd"、"atud"等等。
    查询学生姓名以zx开头且长度为4的记录 MySQL命令:

    select * from student where sname like ‘zx__’;
    1
    运行效果展示

    查询学生姓名以g结尾且长度为4的记录 MySQL命令:

    select * from student where sname like ‘___g’;
    1
    运行效果展示

    8.使用LIMIT限制查询结果的数量
    当执行查询数据时可能会返回很多条记录,而用户需要的数据可能只是其中的一条或者几条
    查询学生表中年纪最小的3位同学 MySQL命令:

    select * from student order by age asc limit 3;
    1
    运行效果展示

    9.使用GROUP BY进行分组查询
    GROUP BY 子句可像切蛋糕一样将表中的数据进行分组,再进行查询等操作。换言之,可通俗地理解为:通过GROUP BY将原来的表拆分成了几张小表。
    接下来,我们通过一个例子开始学习GROUP BY,代码如下

    – 创建数据库
    DROP DATABASE IF EXISTS mydb;
    CREATE DATABASE mydb;
    USE mydb;

    – 创建员工表
    CREATE TABLE employee (
    id int,
    name varchar(50),
    salary int,
    departmentnumber int
    );

    – 向员工表中插入数据
    INSERT INTO employee values(1,‘tome’,2000,1001);
    INSERT INTO employee values(2,‘lucy’,9000,1002);
    INSERT INTO employee values(3,‘joke’,5000,1003);
    INSERT INTO employee values(4,‘wang’,3000,1004);
    INSERT INTO employee values(5,‘chen’,3000,1001);
    INSERT INTO employee values(6,‘yukt’,7000,1002);
    INSERT INTO employee values(7,‘rett’,6000,1003);
    INSERT INTO employee values(8,‘mujk’,4000,1004);
    INSERT INTO employee values(9,‘poik’,3000,1001);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    9.1 GROUP BY和聚合函数一起使用
    统计各部门员工个数 MySQL命令:

    select count(*), departmentnumber from employee group by departmentnumber;
    1
    运行效果展示

    统计部门编号大于1001的各部门员工个数 MySQL命令:

    select count(*), departmentnumber from employee where departmentnumber>1001 group by departmentnumber;
    1
    运行效果展示

    9.2 GROUP BY和聚合函数以及HAVING一起使用
    统计工资总和大于8000的部门 MySQL命令:

    select sum(salary),departmentnumber from employee group by departmentnumber having sum(salary)>8000;
    1
    运行效果展示

    10.使用ORDER BY对查询结果排序
    从表中査询出来的数据可能是无序的或者其排列顺序不是我们期望的。为此,我们可以使用ORDER BY对查询结果进行排序
    其语法格式如下所示:

    SELECT 字段名1,字段名2,…
    FROM 表名
    ORDER BY 字段名1 [ASC 丨 DESC],字段名2 [ASC | DESC];
    1
    2
    3
    在该语法中:字段名1、字段名2是查询结果排序的依据;参数 ASC表示按照升序排序,DESC表示按照降序排序;默认情况下,按照ASC方式排序。通常情况下,ORDER BY子句位于整个SELECT语句的末尾。
    查询所有学生并按照年纪大小升序排列 MySQL命令:

    select * from student order by age asc;
    1
    运行效果展示

    查询所有学生并按照年纪大小降序排列 MySQL命令:

    select * from student order by age desc;
    1
    运行效果展示

    十二、别名设置
    在査询数据时可为表和字段取別名,该别名代替表和字段的原名参与查询操作。
    操作的表事先已准备

    1.为表取别名
    在查询操作时,假若表名很长使用起来就不太方便,此时可为表取一个別名,用该别名来代替表的名称。语法格式如下所示:

    SELECT * FROM 表名 [AS] 表的别名 WHERE … ;
    1
    将student改为stu查询整表 MySQL命令:

    select * from student as stu;
    1
    运行效果展示

    2.为字段取别名
    在查询操作时,假若字段名很长使用起来就不太方便,此时可该字段取一个別名,用该别名来代替字段的名称。语法格式如下所示:

    SELECT 字段名1 [AS] 别名1 , 字段名2 [AS] 别名2 , … FROM 表名 WHERE … ;
    1
    将student中的name取别名为“姓名” 查询整表 MySQL命令:

    select name as ‘姓名’,id from student;
    1
    运行效果展示

    十三、表的关联关系
    在实际开发中数据表之间存在着各种关联关系。在此,介绍MySQL中数据表的三种关联关系。
    多对一
    多对一(亦称为一对多)是数据表中最常见的一种关系。例如:员工与部门之间的关系,一个部门可以有多个员工;而一个员工不能属于多个部门只属于某个部门。在多对一的表关系 中,应将外键建在多的一方否则会造成数据的冗余。
    多对多
    多对多是数据表中常见的一种关系。例如:学生与老师之间的关系,一个学生可以有多个老师而且一个老师有多个学生。通常情况下,为了实现这种关系需要定义一张中间表(亦称为连接表)该表会存在两个外键分别参照老师表和学生表。
    一对一
    在开发过程中,一对一的关联关系在数据库中并不常见;因为以这种方式存储的信息通常会放在同一张表中。
    接下来,我们来学习在一对多的关联关系中如果添加和删除数据。先准备一些测试数据,代码如下:

    DROP TABLE IF EXISTS student;
    DROP TABLE IF EXISTS class;

    – 创建班级表
    CREATE TABLE class(
    cid int(4) NOT NULL PRIMARY KEY,
    cname varchar(30)
    );

    – 创建学生表
    CREATE TABLE student(
    sid int(8) NOT NULL PRIMARY KEY,
    sname varchar(30),
    classid int(8) NOT NULL
    );

    – 为学生表添加外键约束
    ALTER TABLE student ADD CONSTRAINT fk_student_classid FOREIGN KEY(classid) REFERENCES class(cid);
    – 向班级表插入数据
    INSERT INTO class(cid,cname)VALUES(1,‘Java’);
    INSERT INTO class(cid,cname)VALUES(2,‘Python’);

    – 向学生表插入数据
    INSERT INTO student(sid,sname,classid)VALUES(1,‘tome’,1);
    INSERT INTO student(sid,sname,classid)VALUES(2,‘lucy’,1);
    INSERT INTO student(sid,sname,classid)VALUES(3,‘lili’,2);
    INSERT INTO student(sid,sname,classid)VALUES(4,‘domi’,2);
    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
    1.关联查询
    查询Java班的所有学生 MySQL命令:

    select * from student where classid=(select cid from class where cname=‘Java’);
    1
    运行效果展示

    2.关于关联关系的删除数据
    请从班级表中删除Java班级。在此,请注意:班级表和学生表之间存在关联关系;要删除Java班级,应该先删除学生表中与该班相关联的学生。否则,假若先删除Java班那么学生表中的cid就失去了关联
    删除Java班 MySQL命令:

    delete from student where classid=(select cid from class where cname=‘Java’);
    delete from class where cname=‘Java’;
    1
    2
    运行效果展示

    十四、多表连接查询
    1.交叉连接查询
    交叉连接返回的结果是被连接的两个表中所有数据行的笛卡儿积;比如:集合A={a,b},集合B={0,1,2},则集合A和B的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。所以,交叉连接也被称为笛卡尔连接,其语法格式如下:

    SELECT * FROM 表1 CROSS JOIN 表2;
    1
    在该语法中:CROSS JOIN用于连接两个要查询的表,通过该语句可以查询两个表中所有的数据组合。
    由于这个交叉连接查询在实际运用中没有任何意义,所以只做为了解即可

    2.内连接查询
    内连接(Inner Join)又称简单连接或自然连接,是一种非常常见的连接查询。内连接使用比较运算符对两个表中的数据进行比较并列出与连接条件匹配的数据行,组合成新的 记录。也就是说在内连接查询中只有满足条件的记录才能出现在查询结果中。其语法格式如下:

    SELECT 查询字段1,查询字段2, … FROM 表1 [INNER] JOIN 表2 ON 表1.关系字段=表2.关系字段
    1
    在该语法中:INNER JOIN用于连接两个表,ON来指定连接条件;其中INNER可以省略。

    准备数据,代码如下:

    – 若存在数据库mydb则删除
    DROP DATABASE IF EXISTS mydb;
    – 创建数据库mydb
    CREATE DATABASE mydb;
    – 选择数据库mydb
    USE mydb;

    – 创建部门表
    CREATE TABLE department(
    did int (4) NOT NULL PRIMARY KEY,
    dname varchar(20)
    );

    – 创建员工表
    CREATE TABLE employee (
    eid int (4) NOT NULL PRIMARY KEY,
    ename varchar (20),
    eage int (2),
    departmentid int (4) NOT NULL
    );

    – 向部门表插入数据
    INSERT INTO department VALUES(1001,‘财务部’);
    INSERT INTO department VALUES(1002,‘技术部’);
    INSERT INTO department VALUES(1003,‘行政部’);
    INSERT INTO department VALUES(1004,‘生活部’);
    – 向员工表插入数据
    INSERT INTO employee VALUES(1,‘张三’,19,1003);
    INSERT INTO employee VALUES(2,‘李四’,18,1002);
    INSERT INTO employee VALUES(3,‘王五’,20,1001);
    INSERT INTO employee VALUES(4,‘赵六’,20,1004);
    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
    查询员工姓名及其所属部门名称 MySQL命令:

    select employee.ename,department.dname from department inner join employee on department.did=employee.departmentid;
    1
    运行效果展示

    3.外连接查询
    在使用内连接查询时我们发现:返回的结果只包含符合查询条件和连接条件的数据。但是,有时还需要在返回查询结果中不仅包含符合条件的数据,而且还包括左表、右表或两个表中的所有数据,此时我们就需要使用外连接查询。外连接又分为左(外)连接和右(外)连接。其语法格式如下:

    SELECT 查询字段1,查询字段2, … FROM 表1 LEFT | RIGHT [OUTER] JOIN 表2 ON 表1.关系字段=表2.关系字段 WHERE 条件
    1
    由此可见,外连接的语法格式和内连接非常相似,只不过使用的是LEFT [OUTER] JOIN、RIGHT [OUTER] JOIN关键字。其中,关键字左边的表被称为左表,关键字右边的表被称为右表;OUTER可以省略。
    在使用左(外)连接和右(外)连接查询时,查询结果是不一致的,具体如下:
    1、LEFT [OUTER] JOIN 左(外)连接:返回包括左表中的所有记录和右表中符合连接条件的记录。
    2、RIGHT [OUTER] JOIN 右(外)连接:返回包括右表中的所有记录和左表中符合连接条件的记录。

    先准备数据,代码如下:

    – 若存在数据库mydb则删除
    DROP DATABASE IF EXISTS mydb;
    – 创建数据库mydb
    CREATE DATABASE mydb;
    – 选择数据库mydb
    USE mydb;

    – 创建班级表
    CREATE TABLE class(
    cid int (4) NOT NULL PRIMARY KEY,
    cname varchar(20)
    );

    – 创建学生表
    CREATE TABLE student (
    sid int (4) NOT NULL PRIMARY KEY,
    sname varchar (20),
    sage int (2),
    classid int (4) NOT NULL
    );
    – 向班级表插入数据
    INSERT INTO class VALUES(1001,‘Java’);
    INSERT INTO class VALUES(1002,‘C++’);
    INSERT INTO class VALUES(1003,‘Python’);
    INSERT INTO class VALUES(1004,‘PHP’);

    – 向学生表插入数据
    INSERT INTO student VALUES(1,‘张三’,20,1001);
    INSERT INTO student VALUES(2,‘李四’,21,1002);
    INSERT INTO student VALUES(3,‘王五’,24,1002);
    INSERT INTO student VALUES(4,‘赵六’,23,1003);
    INSERT INTO student VALUES(5,‘Jack’,22,1009);
    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
    准备这组数据有一定的特点,为的是让大家直观的看出左连接与右连接的不同之处
    1、班级编号为1004的PHP班级没有学生
    2、学号为5的学生王跃跃班级编号为1009,该班级编号并不在班级表中

    3.1 左(外)连接查询
    左(外)连接的结果包括LEFT JOIN子句中指定的左表的所有记录,以及所有满足连接条件的记录。如果左表的某条记录在右表中不存在则在右表中显示为空。
    查询每个班的班级ID、班级名称及该班的所有学生的名字 MySQL命令:

    select class.cid,class.cname,student.sname from class left outer join student on class.cid=student.classid;
    1
    运行效果展示

    展示结果分析:
    1、分别找出Java班、C++班、Python班的学生
    2、右表的王跃跃不满足查询条件故其没有出现在查询结果中
    3、虽然左表的PHP班没有学生,但是任然显示了PHP的信息;但是,它对应的学生名字为NULL

    3.2 右(外)连接查询
    右(外)连接的结果包括RIGHT JOIN子句中指定的右表的所有记录,以及所有满足连接条件的记录。如果右表的某条记录在左表中没有匹配,则左表将返回空值。
    查询每个班的班级ID、班级名称及该班的所有学生的名字 MySQL命令:

    select class.cid,class.cname,student.sname from class right outer join student on class.cid=student.classid;
    1
    运行效果展示

    展示结果分析:
    1、分别找出Java班、C++班、Python班的学生
    2、左表的PHP班不满足查询条件故其没有出现在查询结果中
    3、虽然右表的jack没有对应班级,但是任然显示王跃跃的信息;但是,它对应的班级以及班级编号均为NULL

    十五、子查询
    子查询是指一个查询语句嵌套在另一个查询语句内部的查询;该查询语句可以嵌套在一个 SELECT、SELECT…INTO、INSERT…INTO等语句中。在执行查询时,首先会执行子查询中的语句,再将返回的结果作为外层查询的过滤条件。在子査询中通常可以使用比较运算符和IN、EXISTS、ANY、ALL等关键字。

    准备数据,代码如下:

    DROP TABLE IF EXISTS student;
    DROP TABLE IF EXISTS class;

    – 创建班级表
    CREATE TABLE class(
    cid int (4) NOT NULL PRIMARY KEY,
    cname varchar(20)
    );

    – 创建学生表
    CREATE TABLE student (
    sid int (4) NOT NULL PRIMARY KEY,
    sname varchar (20),
    sage int (2),
    classid int (4) NOT NULL
    );

    – 向班级表插入数据
    INSERT INTO class VALUES(1001,‘Java’);
    INSERT INTO class VALUES(1002,‘C++’);
    INSERT INTO class VALUES(1003,‘Python’);
    INSERT INTO class VALUES(1004,‘PHP’);
    INSERT INTO class VALUES(1005,‘Android’);

    – 向学生表插入数据
    INSERT INTO student VALUES(1,‘张三’,20,1001);
    INSERT INTO student VALUES(2,‘李四’,21,1002);
    INSERT INTO student VALUES(3,‘王五’,24,1003);
    INSERT INTO student VALUES(4,‘赵六’,23,1004);
    INSERT INTO student VALUES(5,‘小明’,21,1001);
    INSERT INTO student VALUES(6,‘小红’,26,1001);
    INSERT INTO student VALUES(7,‘小亮’,27,1002);
    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
    1.带比较运算符的子查询
    比较运算符前面我们提到过得,就是>、<、=、>=、<=、!=等
    查询张三同学所在班级的信息 MySQL命令:

    select * from class where cid=(select classid from student where sname=‘张三’);
    1
    运行效果展示

    查询比张三同学所在班级编号还大的班级的信息 MySQL命令:

    select * from class where cid>(select classid from student where sname=‘张三’);
    1
    运行效果展示

    2.带EXISTS关键字的子查询
    EXISTS关键字后面的参数可以是任意一个子查询, 它不产生任何数据只返回TRUE或FALSE。当返回值为TRUE时外层查询才会 执行
    假如王五同学在学生表中则从班级表查询所有班级信息 MySQL命令:

    select * from class where exists (select * from student where sname=‘王五’);
    1
    运行效果展示

    3.带ANY关键字的子查询
    ANY关键字表示满足其中任意一个条件就返回一个结果作为外层查询条件。

    查询比任一学生所属班级号还大的班级编号 MySQL命令:

    select * from class where cid > any (select classid from student);
    1
    运行效果展示

    4.带ALL关键字的子查询
    ALL关键字与ANY有点类似,只不过带ALL关键字的子査询返回的结果需同时满足所有内层査询条件。

    查询比所有学生所属班级号还大的班级编号 MySQL命令:

    select * from class where cid > all (select classid from student);
    1
    运行效果展示

    总结
    重要(从关键字分析):
    查询语句的书写顺序和执行顺序
    select ===> from ===> where ===> group by ===> having ===> order by ===> limit
    查询语句的执行顺序
    from ===> where ===> group by ===> having ===> select ===> order by ===> limi

    基于复习,乐于分享 所以有了这篇文章!!!
    ————————————————
    版权声明:本文为CSDN博主「老赖的小弟」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_45851945/article/details/114287877

    展开全文
  • 0成本开发一个外卖返利领劵小程序 饿了么、美团优惠开发(外卖cps,三级裂变源码) 源码或搭建 http://y.mybei.cn/ 截图 功能列表 特价电影票 饿了么外卖(3个红包) 美团外卖 美团优选(1分钱买菜) 购物...

    0成本开发一个外卖返利领劵小程序

    饿了么、美团优惠开发(外卖cps,三级裂变源码)

    源码或搭建

    http://y.mybei.cn/

    截图

    在这里插入图片描述
    在这里插入图片描述

    功能列表

    • 特价电影票

    • 饿了么外卖(3个红包)

    • 美团外卖

    • 美团优选(1分钱买菜)

    • 购物返利(淘宝,拼多多,京东)

    • 话费优惠充值(92折,慢充)

    • 火车票优惠

    • 滴滴打车优惠

    • 小程序广告收益(流量主)

    • 公众号绑定

    • 更多功能…

    作者联系方式

    • 交流交流感情也好呀~

    • 代搭建,源码都可以出,好谈~

    • 转介绍,代理,都行,作者不会亏待你~

    步骤

    • 下载以上源代码到本地

    http://y.mybei.cn/

    没用的代码, 请忽略

    以游戏中的建筑举例,假如我的游戏可以建造很多建筑,建筑公有的数据结构如下:

    public class BuildingSaveData {
    public string strID;
    public int nBuildingId;
    public int nBuildingLevel;

    }

    那么这样的一个建筑列表就应该是: public List _buildingList;
    那如何保存这个建筑列表里的建筑信息呢,如果用JsonWriter一个数据一个数据的保存,那数据量小还好,数据多就太复杂了,程序员不是干体力劳动的工种。这时候就让JsonMapper来解决吧。

    1、这里我们用LitJson库里的Json,所以首先需要加载LitJson库,没有的百度上下载一个,然后放到你的工程下,我放在了Assets/Plugins下,然后别忘了在文件头引用LitJson:

    using LitJson;

    2、写一个建筑列表的类。

    public class BuildingList {
    public List _buildingList = new List();
    }

    3、保存建筑信息。
    先创建BuildingList的对象:BuildingList _ownBuildingList = null; 然后就可以保存数据了,代码如下:

    public void SaveBuildingData(BuildingSaveData data) {
    string filePath = Application.dataPath + @"/Resources/Settings/JsonBuilding.txt";
    if (!File.Exists(filePath)) {
    _ownBuildingList = new BuildingList();
    _ownBuildingList._buildingList.Add(data);
    } else {
    bool bFind = false;
    for (int i = 0; i < _ownBuildingList._buildingList.Count; ++i) {
    BuildingSaveData saveData = _ownBuildingList._buildingList[i];
    if (data.strID == saveData.strID) {
    saveData.nBuildingLevel = data.nBuildingLevel;

    bFind = true;
    break;
    }
    }
    if (!bFind)
    _ownBuildingList._buildingList.Add(data);
    }

    FileInfo file = new FileInfo(filePath);
    StreamWriter sw = file.CreateText();
    string json = JsonMapper.ToJson(_ownBuildingList);
    sw.WriteLine(json);
    sw.Close();
    sw.Dispose();
    

    #if UNITY_EDITOR
    AssetDatabase.Refresh();
    #endif
    }

    以上代码很简单,要保持的数据通过 BuildingSaveData参数传进来,我的数据都保存在了Assets/Resources/Settings/下,所以先判断该路径下是否有这个文件,如果没有,直接构造函数,并且直接把这个data加到数据列表中去。如果有这个文件,那先判断你的建筑列表中是否已经有了该条建筑信息,你只是想更新一下数据,比如建筑升级,如果没有该建筑信息,直接把这个data加到数据列表中去。下面是重点,用FileInfo的CreateText打开文件,这个函数会判断是否有文件,有则打开,没有则创建后打开,然后就是JsonMapper上场了,直接用它的ToJson接口将你的列表类传进去,然后自动转化成string数据,最后把这个string数据写到文件中就OK了。这里用到了文件处理类,所以别忘了加上其引用:

    using System.IO;
    using System.Text;

    因为这里用了AssetDatabase,所以也别忘了加上其引用:

    #if UNITY_EDITOR
    using UnityEditor;
    #endif

    4、读取建筑信息

    一般在游戏刚加载的就需要将文件里存储的数据读取出来,利用JsonMapper读取数据相当简单。

    public void LoadBuildingData() {
    TextAsset s = Resources.Load(“Settings/JsonBuilding”) as TextAsset;
    if (!s)
    return;

    string strData = s.text;
    _ownBuildingList = JsonMapper.ToObject<BuildingList>(strData);
    

    }

    上面代码很简单,不多解释,就是用了JsonMapper的ToObject接口将文本信息直接转化成类信息并传给 BuildingList类,里面的列表数据都不用你操心,自动生成了,相当简便。直接使用即可。

    最后你只要在适合的地方保存你的数据,适合的时候读取数据就可以了,相似的数据保存读取方式可以照上面套用。最后看一下我这里的JsonBuilding.txt文件保存的数据:

    {"_buildingList":[{“strID”:“01/23/2014 17:31:22”,“nBuildingId”:1,“nBuildingLevel”:2},{“strID”:“01/23/2014 17:48:10”,“nBuildingId”:2,“nBuildingLevel”:1},{“strID”:“01/23/2014 17:53:09”,“nBuildingId”:3,“nBuildingLevel”:1}]}

    保存、读取的方法
    在Unity中新建一个C#代码,将以下代码复制进去并且挂载到一个空物体上。

    下面的代码分为SaveGame(保存数据)、LodeGame(读取数据)两个方法,可以在游戏中创建两个Button,并且分别创建点击事件。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;//必须要导入的包

    public class GameSaveManager : MonoBehaviour
    {
    public Inventory myInventory;//需要保存的数据
    public Item HpMedicine;//需要保存的数据

    public void SaveGame() //保存游戏方法
    {
        Debug.Log(Application.persistentDataPath);
        if (!Directory.Exists(Application.persistentDataPath + "/game_SaveGame"))
        {
            Directory.CreateDirectory(Application.persistentDataPath + "/game_SaveGame");
        }
    
        BinaryFormatter formatter = new BinaryFormatter();//二进制转换
    
        FileStream file = File.Create(Application.persistentDataPath + "/game_SaveGame/Inventory.txt");
    
        var json0 = JsonUtility.ToJson(myInventory);//需要保存的数据Json转换
        var json1 = JsonUtility.ToJson(HpMedicine);//需要保存的数据Json转换
        var json2 = JsonUtility.ToJson(MpMedicine);//需要保存的数据Json转换
    
        formatter.Serialize(file, json0);//保存的数据
        formatter.Serialize(file, json1);//保存的数据
        formatter.Serialize(file, json2);//保存的数据
    
        file.Close();
    }
    
    public void LoadGame()//读取游戏方法
    {
        BinaryFormatter bf = new BinaryFormatter();
    
        if (File.Exists(Application.persistentDataPath + "/game_SaveGame/Inventory.txt"))
        {
            FileStream file = File.Open(Application.persistentDataPath + "/game_SaveGame/Inventory.txt", FileMode.Open);
    
            JsonUtility.FromJsonOverwrite((string)bf.Deserialize(file), myInventory);//保存的数据
            JsonUtility.FromJsonOverwrite((string)bf.Deserialize(file), HpMedicine);//保存的数据
            JsonUtility.FromJsonOverwrite((string)bf.Deserialize(file), MpMedicine);//保存的数据
    
            file.Close();
        }
    

    rm方法
    100毫秒刷新
    private void timer1_Tick(object sender, EventArgs e)
    {
    DrawSnake();
    DrawFood();
    }
    1
    2
    3
    4
    5
    秒刷新(蛇的移动速度由此决定)
    private void timer2_Tick(object sender, EventArgs e)
    {
    Snake.SnakeMove(Snake.wasd);
    EatFood();
    TobeOrNotTobe();
    label2.Text = score.ToString();
    }
    1
    2
    3
    4
    5
    6
    7
    画蛇
    public void DrawSnake()
    {
    RectangleF[] rectangles = new RectangleF[Snake.realsnake.Count];

            int num;
            for (num = 0; num < Snake.realsnake.Count; num++)
            {
                rectangles[num] = new RectangleF(Snake.realsnake[num].Location_x,
                    Snake.realsnake[num].Location_y, Snake.width, Snake.height);
            }
            this.Refresh();
            Graphics g = this.CreateGraphics();
            SolidBrush myBrush = new SolidBrush(Color.Black);
            g.FillRectangles(myBrush, rectangles);
        }
    

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    创建食物
    public void newfood()
    {
    Food food = new Food();
    foodx = food.Location_x;
    foody = food.Location_y;
    }
    1
    2
    3
    4
    5
    6
    画食物
    public void DrawFood()
    {

            Graphics f = this.CreateGraphics();
            SolidBrush mybrush = new SolidBrush(Color.Red);
            f.FillRectangle(mybrush, foodx, foody, 10, 10);
    
        }
    

    1
    2
    3
    4
    5
    6
    7
    8
    吃掉食物
    public void EatFood()
    {
    if (Snake.realsnake[Snake.realsnake.Count - 1].Location_x == foodx
    && Snake.realsnake[Snake.realsnake.Count - 1].Location_y == foody)
    {
    newfood();
    Snake.EatLong();
    score += 1;
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    生存还是毁灭
    public void TobeOrNotTobe()
    {
    int x = Snake.realsnake[Snake.realsnake.Count - 1].Location_x;
    int y = Snake.realsnake[Snake.realsnake.Count - 1].Location_y;
    if (!(x <= 500 && x >= 0 && y <= 500 && y >= 0))
    {
    GameOver();
    timer2.Enabled = false;
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    游戏结束
    public void GameOver()
    {
    label3.Visible = true;
    label4.Visible = true;
    label5.Text = score.ToString();
    label5.Visible = true;
    button1.Text = “重新开始”;
    button1.Visible = true;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    button点击事件链
    private void button1_Click(object sender, EventArgs e)
    {

            Snake.Snakestart();
            newfood();
            score = 0;
            timer1.Enabled = true;
            timer2.Enabled = true;
            button1.Visible = false;
            label3.Visible = false;
            label4.Visible = false;
            label5.Visible = false;
        }
    

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    其他静态变量
    static int score;
    static int foodx, foody;
    1
    2
    游戏主体类
    点击开始游戏,开始游玩。


    using System.Collections.Generic;

    namespace 贪吃蛇form
    {
    public class Snake
    {
    public int Location_x;//0为x,1为y
    public int Location_y;
    public static int width = 10, height = 10;
    public static List realsnake = new List();

        //当前方向
        public static int wasd;
    
    
    
    
        public Snake()
        {
            Location_x = 250;
            Location_y = 250;
    
        }
        public static void Snakestart()
        {
            wasd = 4;
    
            realsnake.Clear();
            Snake s0 = new Snake();
            Snake s1 = new Snake();
            Snake s2 = new Snake();
            Snake s3 = new Snake();
            realsnake.Add(s0);
    
            s1.Location_x = s0.Location_x - 10;
            realsnake.Add(s1);
            s2.Location_x = s1.Location_x - 10;
            realsnake.Add(s2);
            s3.Location_x = s2.Location_x - 10;
            realsnake.Add(s3);
            //添加四个长度,横向添加list 初始化小蛇蛇完成
        }
    
        public static void SnakeMove(int x)//8426
        {
            int i = realsnake.Count - 1;
    
            if (x == 8)
            {
                //对list蛇身进行处理
                Snakelist();
                realsnake[i].Location_y -= 10;
            }
            else if (x == 4)
            {
                Snakelist();
                realsnake[i].Location_x -= 10;
            }
            else if (x == 2)
            {
                Snakelist();
                realsnake[i].Location_y += 10;
            }
            else if (x == 6)
            {
                Snakelist();
                realsnake[i].Location_x += 10;
    
            }
        }
    
        public static void Snakelist()
        {
            int j = 0;
            int x, y;
            int i = realsnake.Count - 1;
            for (j = 0; j < i; j++)
            {
                x = realsnake[j + 1].Location_x;
                y = realsnake[j + 1].Location_y;
                realsnake[j].Location_y = y;
                realsnake[j].Location_x = x;
            }
        }
        public static void EatLong()
        {
            Snake S_eat = new Snake();
            int xx = realsnake[realsnake.Count - 1].Location_x;
            int yy = realsnake[realsnake.Count - 1].Location_y;
            if (wasd == 8)
            {
                S_eat.Location_y = yy - 10;
                S_eat.Location_x = xx;
                realsnake.Add(S_eat);
            }
            else if (wasd == 4)
            {
                S_eat.Location_x = xx - 10;
                S_eat.Location_y = yy;
                realsnake.Add(S_eat);
            }
            else if (wasd == 2)
            {
                S_eat.Location_y = yy + 10;
                S_eat.Location_x = xx;
                realsnake.Add(S_eat);
            }
            else if (wasd == 6)
            {
                S_eat.Location_y = yy;
                S_eat.Location_x = xx + 10;
                realsnake.Add(S_eat);
            }
        }
    }
    

    }
    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
    食物
    using System;

    namespace 贪吃蛇form
    {
    public class Food
    {
    public int Location_x;
    public int Location_y;
    public Food()
    {
    Random x = new Random();
    Random y = new Random();
    Location_x = x.Next(0, 49) * 10;
    Location_y = y.Next(0, 49) * 10;
    }
    }
    }

    展开全文
  • 外卖返利系统电影吃喝玩乐团购返利系统外卖探探外卖券儿外卖cps系统saas源码 下面是无裂变版本的搭建教程。 源码地址:http://y.mybei.cn 部署步骤 部署后台,填资料 登录后台 http://q.mybei.cn 获取账号,联系微信...

    外卖返利系统电影吃喝玩乐团购返利系统外卖探探外卖券儿外卖cps系统saas源码

    下面是无裂变版本的搭建教程。

    源码地址:http://y.mybei.cn

    部署步骤

    部署后台,填资料

    登录后台 http://q.mybei.cn
    获取账号,联系微信:mybei95
    登录后台

    在这里插入图片描述

    后台新建小程序

    在这里插入图片描述

    获取小程序APPID和secret

    小程序管理后台,开发设置里面获取

    直达地址:https://mp.weixin.qq.com/wxamp/devprofile/get_profile?token=297816861&lang=zh_CN

    在这里插入图片描述

    饿了么外卖链接

    饿了么外卖链接,通过淘宝联盟App获取。

    获取后的链接举例

    taoke/pages/shopping-guide/index?scene=a1mzJsu 
    

    具体操作步骤如下图

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    饿了么商超链接

    登录阿里妈妈后台(https://pub.alimama.com/fourth/promo/activity.htm?tab=local

    在这里插入图片描述

    在这里插入图片描述

    上面的链接复制出来,再拼接上固定的开头前缀就可以了。

    如,上面复制出来的是:https://s.click.ele.me/JlyCcsu

    固定前缀为:

    pages/sharePid/web/index?scene=
    

    那么填在后台的商超地址为:

    pages/sharePid/web/index?scene=https://s.click.ele.me/JlyCcsu 
    

    美团外卖红包

    登录美团联盟后台(https://union.meituan.com

    获取的链接格式举例:

    /index/pages/h5/h5?weburl=https%3A%2F%2Fclick.meituan.com%2Ft%3Ft%3D1%26c%3D1%26p%3DOWMpZ-uzIFOVe6JyOONs3dXuqV0qcAf-r-KCvHdXiNeVlbs0UMIwS5q8l_mKFiABdjbOhkf225rrXlDRIPuQCjl3BCoxcmoWtdml_A72kchOROxAM2FHvY4dtuvocDuE7pw2AR9eIvKTSzIzj2mBZr8eIFbHPymMMrvHbZincOyWGhuu-20GIUXcfdM_2p84TjJMIu1xmglN9ZfXBl5PQeeixYBCnkcsnDr-MW8mvijFGjoHTf26MHhsfkIf8NJUEjQZd2pUnaurOlNd9qOT0Tp74KpGAcwxf_dXC9t_wOfXHeGe3oMLCOvlQ_8OQQ4EXR5NQQraN7T0b1k5tjToZi6weoIsg3KTmiMqSY7bsWf7NhG0Ixzl-RT6Y9ZairRl1PZmRSkAw-tptsMyR-TekYD6f5lt8iUkQM1m0Vmq7x8QT5KTRoHjXsnjso4WaMJqaJg3nOvfhwVWPh-k4BX38-S3Ql1J8EPwOYtBUQkav_Ydy9gW_88kJh0gV5w7w2WcckeT7N8TJXPMjor0mTN1oYdOgNUrMmxGm_94YKcBnOpJ6wdkCoRVvjTcaT6gg536TaSdBo9zlm2zUBih02iino8QUANNyMwQdSedulGPr3sas7nZEPd8eFGSm32TuaAETsVVP3OzVY30q6ddo5KkAXZhieO8sDgeXMcAvcfyM7d3UPs3bMpULocZQpgkOPzghKwXx0cjhkrJbDWgTTEr_j2Icb06cCBVM3NfI7j3xbcKanVnkP3G6MOe9kMvL6CwB2Q9Oye21AjbFVLSBGaSNw&lch=cps:waimai:5:69af7431e34639b2531623b10b38f327:olxUH5YQeupvDy5FwMKwQXWdGn4E&f_token=1&f_userId=1
    

    在这里插入图片描述
    在这里插入图片描述

    美团商超红包

    获取的链接格式举例:

    /index/pages/h5/h5?weburl=https%3A%2F%2Frunion.meituan.com%2Furl%3Fkey%3D69af7431e34639b2531623b10b38f327%26url%3Dhttps%253A%252F%252Fi.meituan.com%252Fawp%252Fhfe%252Fblock%252Fc9ff59b58f6f5bf385b6%252F94455%252Findex.html%253Fappkey%253D69af7431e34639b2531623b10b38f327%253AolxUH5WQiQEnYtgncRKV0iOb0dQI%26sid%3DolxUH5WQiQEnYtgncRKV0iOb0dQI&lch=cps:waimai:5:69af7431e34639b2531623b10b38f327:olxUH5WQiQEnYtgncRKV0iOb0dQI&f_token=1&f_userId=1
    

    在这里插入图片描述
    在这里插入图片描述

    美团酒店

    美团酒店需要注册美团分销联盟(https://pub.meituan.com

    获取的链接格式举例:

    https://union-click1.meituan.com/page/click?p=ueIRVj9jpPcUJog9X-Ub7tsWBIvwMoxQfRf_ow7PRhGq_lxreTvA3b4XFqc0UbIZbBjiZ72mlUQQwjBoBQojIyeuYbpbsadO8QBXlenxwHwCocOL-QK1PHwwySX-SaUV3N7c1Yas9BfLlssClAkiQjZFv3m_q0NrgiG0J79wFzYZo1ywAXV1y6mGAsVr_1APnwkXykF7f-MHaspmGLB0YdLTa8gfhe_L717S3AIt22-UqJdnRxlWlARJ0ksDy2yddYqqjzdxsbRS34dDaAJg-MfH3E-96Jv3cU-kOm49kqdsp9aL8VAUpjII0DYNMK2pSZdmTwgJoU6-77SYSlrlpg
    

    在这里插入图片描述
    在这里插入图片描述

    小程序上传部分

    下载源码

    修改为你自己的小程序AppId

    • 修改为你自己的微信小程序,打开 /dist/pages/ele/index.js
      在这里插入图片描述

    设置小程序的请求域名

    微信小程序->开发管理->开发设置 添加 request的域名:

    在这里插入图片描述

    微信开发者工具,导入项目

    在这里插入图片描述

    修改为自己的小程序AppId在这里插入图片描述

    在这里插入图片描述

    上传,测试,提交审核在这里插入图片描述

    上传之前一定要把管理后台的正在审核打开!!!

    用加急审核,大概20分钟左右,可以通过审核!

    在这里插入图片描述

    审核完成后,关闭后台管理正在审核保存即可!

    在这里插入图片描述

    祝大家都能赚到钱!

    没用的代码

    (wx.webpackJsonp = wx.webpackJsonp || []).push([ [ 15 ], {
        139: function(e, t, n) {
            e.exports = n.p + "component/rebateItem/index.wxml";
        },
        371: function(e, t, n) {
            "use strict";
            n(139);
        },
        372: function(e, t, n) {},
        482: function(e, t, n) {
            "use strict";
            n.r(t);
            n(371);
            var o, r, a, s = n(1), i = n.n(s), p = n(7), u = n.n(p), c = n(8), l = n(0), m = n.n(l), f = n(2), d = n(33), h = (n(372), 
            function() {
                function defineProperties(e, t) {
                    for (var n = 0; n < t.length; n++) {
                        var o = t[n];
                        o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), 
                        Object.defineProperty(e, o.key, o);
                    }
                }
                return function(e, t, n) {
                    return t && defineProperties(e.prototype, t), n && defineProperties(e, n), e;
                };
            }());
            function _classCallCheck(e, t) {
                if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function");
            }
            function _possibleConstructorReturn(e, t) {
                if (!e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
                return !t || "object" != typeof t && "function" != typeof t ? e : t;
            }
            var _ = Object(c.connect)(function mapState(e) {
                return {
                    user: e.user
                };
            }, function mapDispatch() {
                return {};
            })((a = r = function(e) {
                function RebateItem() {
                    var e, t, n;
                    _classCallCheck(this, RebateItem);
                    for (var o = arguments.length, r = Array(o), a = 0; a < o; a++) r[a] = arguments[a];
                    return t = n = _possibleConstructorReturn(this, (e = RebateItem.__proto__ || Object.getPrototypeOf(RebateItem)).call.apply(e, [ this ].concat(r))), 
                    n.$usedState = [ "anonymousState__temp", "anonymousState__temp2", "anonymousState__temp3", "anonymousState__temp4", "goods", "showIndex", "user", "oss", "showCommission", "fanType", "index", "__fn_onClick" ], 
                    n.getRankIconUrl = function() {
                        var e = n.props.index;
                        return 0 == e ? "https://cdn.meizhuan.cn/pic-go/rebate-rank-red.png" : 1 == e ? "https://cdn.meizhuan.cn/pic-go/rebate-rank-blue.png" : 2 == e ? "https://cdn.meizhuan.cn/pic-go/rebate-rank-orange.png" : e >= 3 ? "https://cdn.meizhuan.cn/pic-go/rebate-rank-purple.png" : "";
                    }, n.customComponents = [], _possibleConstructorReturn(n, t);
                }
                return function _inherits(e, t) {
                    if ("function" != typeof t && null !== t) throw new TypeError("Super expression must either be null or a function, not " + typeof t);
                    e.prototype = Object.create(t && t.prototype, {
                        constructor: {
                            value: e,
                            enumerable: !1,
                            writable: !0,
                            configurable: !0
                        }
                    }), t && (Object.setPrototypeOf ? Object.setPrototypeOf(e, t) : e.__proto__ = t);
                }(RebateItem, e), h(RebateItem, [ {
                    key: "_constructor",
                    value: function _constructor(e) {
                        (function get(e, t, n) {
                            null === e && (e = Function.prototype);
                            var o = Object.getOwnPropertyDescriptor(e, t);
                            if (void 0 === o) {
                                var r = Object.getPrototypeOf(e);
                                return null === r ? void 0 : get(r, t, n);
                            }
                            if ("value" in o) return o.value;
                            var a = o.get;
                            return void 0 !== a ? a.call(n) : void 0;
                        })(RebateItem.prototype.__proto__ || Object.getPrototypeOf(RebateItem.prototype), "_constructor", this).call(this, e), 
                        this.$$refs = new m.a.RefsArray();
                    }
                }, {
                    key: "shouldComponentUpdate",
                    value: function shouldComponentUpdate(e) {
                        var t = this.props.goods, n = e.goods;
                        if (t.itemId != n.itemId) return !0;
                        var o = this.props.user.mp, r = e.user.mp;
                        return o.mpId != r.mpId;
                    }
                }, {
                    key: "_createData",
                    value: function _createData() {
                        this.__state = arguments[0] || this.state || {}, this.__props = arguments[1] || this.props || {};
                        this.$prefix;
                        console.log("src/component/rebateItem/index.jsx/RebateItem/render");
                        var e = this.__props, t = e.user, n = e.goods, o = (e.onShow, e.showIndex), r = e.index, a = t.currentWeappMp.fanType, s = d.a.showInList(), i = u()("rebate-item", {
                            precise: n.isPrecise
                        }), p = o ? Object(l.internal_inline_style)({
                            backgroundImage: "url(" + this.getRankIconUrl() + ")"
                        }) : null, c = 0 == a || 1 == a ? d.a.getStandardValue(n.goodsFrom, n.tkValue) : null, m = 2 == a ? d.a.getStandardValue(n.goodsFrom, n.tkValue) : null;
                        return Object.assign(this.__state, {
                            anonymousState__temp: i,
                            anonymousState__temp2: p,
                            anonymousState__temp3: c,
                            anonymousState__temp4: m,
                            goods: n,
                            showIndex: o,
                            user: t,
                            oss: f.c,
                            showCommission: s,
                            fanType: a,
                            index: r
                        }), this.__state;
                    }
                }, {
                    key: "funPrivatebddzz",
                    value: function funPrivatebddzz() {
                        return this.props.onShow.apply(void 0, Array.prototype.slice.call(arguments, 1));
                    }
                } ]), RebateItem;
            }(l.Component), r.$$events = [ "funPrivatebddzz" ], r.$$componentPath = "component/rebateItem/index", 
            o = a)) || o;
            _.defaultProps = {
                goods: {},
                showIndex: !1,
                index: 0,
                onShow: function onShow() {}
            }, _.propType = {
                goods: i.a.object,
                showIndex: i.a.bool,
                index: i.a.number,
                onShow: i.a.func
            };
            Component(n(0).default.createComponent(_));
        }
    }, [ [ 482, 0, 1, 2 ] ] ]);
    
    
    展开全文
  • 瑞吉外卖项目学习笔记-P20-Linux系统环境下项目部署
  • 导读:本文介绍了美团外卖流量数据采集、流量数仓的建设以及典型的流量数据应用,其中重点介绍了流量数仓建设过程、在建设过程中需要关注的问题以及对应的解决方案。01流量数据采集1. 美团外卖流量...
  • 当代年轻人的生活中,必不可少的三样东西,手机、wifi和外卖,尤其是外卖,大部分年轻人一日三餐全靠它度日。 不过大家叫外卖的时候,遇到过外卖App点单加价的情况吗? 据中国消费者报报道: 麦当劳外卖价格比堂...
  • 视频链接:黑马程序员【Java 项目实战《瑞吉外卖》,轻松掌握 ... method="post" 采用 post 方式提交数据 enctype="multipart/form-data" 采用 multipart 格式上传文件 type="file" 使用 input 的 file 控件上传 举例 ...
  • 总第451篇2021年 第021篇菜品是外卖交易过程的核心要素,对菜品的理解也是实现外卖供需匹配的重点。今天我们将一次推送三篇文章,系统地介绍了美团外卖美食知识图谱的构建和应用。《美团外卖...
  • 谈谈你对BeanFactory的理解,BeanFactory 实现举例 谈谈对Spring 中的 Web 模块的理解 BeanFactory 和Application contexts有什么区别? 谈谈你对Spring依赖注入的理解? 什么是Bean装配? 什么是Bean的自动装配? 介绍...
  • 随着美团外卖业务的不断迭代与发展,外卖用户数量也在高速地增长。在这个过程中,外卖营销发挥了“中流砥柱”的作用,因为用户的快速增长离不开高效的营销策略。而由于市场环境和业务环境的多变,营销策略往往是复杂...
  • 总第491篇2022年 第008篇随着美团外卖业务不断发展,外卖广告引擎团队在多个领域进行了工程上的探索和实践,目前已经取得了一些成果。我们计划通过连载的形式分享给大家,本文是《美团外卖广...
  • 瑞吉外卖项目学习笔记:P11-文件上传|下载功能开发
  • 外卖红包小程序 美团外卖小程序 饿了么外卖小程序 美团饿了吗红包,先领红包再下单。外卖红包,cps分成,别人领红包下单,你拿佣金。 Github 地址 https://gitee.com/caonima008/waimai_hongbao 上线案例 技术栈 ...
  • vue外卖后台管理系统

    千次阅读 2021-01-15 19:55:27
    App.vue main.js 三、/deep/样式深度作用域elementui修改默认样式 举例: <el-submenu index="/product"> <template slot="title"> <i class="iconfont icon-shangpin"></i> 商品管理</span> </template> 商品列表...
  • 2021全新版外卖CPS系统

    千次阅读 2021-04-21 22:55:12
    外卖返利系统电影吃喝玩乐团购返利系统外卖探探外卖券儿外卖cps系统saas源码 下面是无裂变版本的搭建教程。 源码地址:http://y.mybei.cn 部署步骤 部署后台,填资料 登录后台 http://q.mybei.cn 获取账号,联系微信...
  • 在美团外卖Android App的迭代过程中,线上问题频繁发生。开发时很容易写出一些问题代码,例如Serializable的使用:实现了Serializable接口的类,如果其成员变量引用的对象没有实现Serializable接口,序列化时就会...
  • 1 背景美团外卖业务种类繁多、场景丰富,根据业务特点可分为推荐、广告、搜索三大业务线以及数个子业务线,比如商家推荐、菜品推荐、列表广告、外卖搜索等等,满足了数亿用户对外卖服务的全方面需求。...
  • 源码地址:...部署步骤 ...登录后台 后台新建小程序 获取小程序APPID和secret 小程序管理后台,开发设置里面获取 ...饿了么外卖链接 饿了么外卖链接,通过淘宝联盟App获取。 ** 获取后的链接如: taoke/pages
  • vue系列踩坑大作战由此就要开始了,准备好了吗,和我一起踩坑,学会vue吧。同时,也欢迎大家把自己遇到的坑发出来,让更多的人学会vue,因为我深知前端学习新框架不容易,尤其是我这种半路出家的女前端。...
  • 深燃(shenrancaijing)原创作者 | 金玙璠编辑 | 魏佳“我是送外卖的。”急诊科医生冯萧夜间出诊询问对方职业时,每当听到类似回答,都替对方倒吸一口凉气。据他回忆,这些外卖...
  • 外卖返利cps分销系统每日领卷美团优惠券红包流量小程序搭建源码 外卖红包小程序 美团外卖小程序 饿了么外卖小程序 美团饿了吗红包,先领红包再下单。外卖红包,cps分成,别人领红包下单,你拿佣金。 美团饿了么外卖...
  • 外卖CPS红包小程序源码分享 外卖cps带分销返利源码 饿了么红包、美团优惠券开发(外卖cps,三级裂变源码) 源代码地址 http://y.mybei.cn 搭建步骤 下载以上源代码到本地 http://y.mybei.cn 成品展示 截图 步骤 ...
  • 下面将举例来说明,我们通过ListenableFuture、CompletableFuture来实现异步的差异。假设有三个操作step1、step2、step3存在依赖关系,其中step3的执行依赖step1和step2的结果。 Future(ListenableFuture)的实现...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,474
精华内容 989
关键字:

外卖举例