Mysql查询某个字段包含某个值

查询字段某一字段中包含某一ID的记录我们可以用以下的方法:

首先创建表:

CREATE TABLE users(id int(6) NOT NULL AUTO_INCREMENT,PRIMARY KEY (id),name VARCHAR(20) NOT NULL,limits VARCHAR(50) NOT NULL);

添加数据:

1、 INSERT INTO users(name, limits) VALUES('小张','1,2,12');

2、 INSERT INTO users(name, limits) VALUES('小王','11,22,32');

如何查询出limits字段中含有ID=2的记录呢,我们可以用以下的方法:

第一种方法:

SELECT * FROM users WHERE limits like "%2%";

执行后您会发现两条数据都被查询了出来,而第2条数据是我们不想要的,所以我们需要对查询进行优化,考虑所有情况:

SELECT * FROM users WHERE limits like "%,2,%," or "2,%" or "%,2" or "2";

另一种方法就是利用mysql 字符串函数 find_in_set()。

第二种方法:
SELECT * FROM users WHERE find_in_set('2', limits);

这一句即可解决。。

另需注意:mysql字符串函数 find_in_set(str1,str2)函数是返回str2中str1所在的位置索引,str2必须以”,”分割开。

MySql基础回顾之表定义

1.创建表

CREATE [TEMPORARY] TABLE tbl_name
(
字段名1 数据类型 [列级完整性约束条件] [默认值],
[字段名2 数据类型 [列级完整性约束条件] [默认值]]
[,…]
[表级完整性约束]
)[ENGINE=引擎类型]

CREATE TABLE  user
(
    `uid` int(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `name` varchar(10) NOT NULL DEFAULT '' COMMENT '姓名',
    `age` int(4) NOT NULL DEFAULT 0 COMMENT '年龄'
)

注:其中“TEMPORARY”为临时表选项,临时表不永久保留,断开连接即自动删除

2.更新表

在MySQL中,通过ALTER TABLE语句来更改原有表结构,常见操作有增加或删减列,创建或取消索引,更改原有列的数据类型、默认值,重命名表名或列名,更改标记注释或引擎类型,更改索引、外键等等

(1)ADD[COLUMN]子句

用于向表中增加列,可同时增加多列

ALTER TABLE USER
ADD `sex` CHAR(1) DEFAULT 1 COMMENT '1为男,0为女' AFTER 'age',
ADD `idcard` VARCHAR(20) COMMENT '身份证'

注:可用关键字“FIRST”将新列置于第一列,也可用关键字“AFTER” 使新列置于某列之后,如“AFTER ”

(2)CHANGE[COLUMN]子句

用于修改列的名称或数据类型

ALTER TABLE user
CHANGE age ages int(4)

注:使用change子句必须写上修改后的数据类型和数据长度,修改列的数据类型可能导致数据丢失或字符串长度不足被截断

(3)ALTER[COLUMN]子句

用于修改或删除列的默认值

ALTER TABLE user
ALTER age SET DEFAULT '1'

(4)MODIFY[COLUMN]子句

与CHANGE子句类型,但MODIFY只修改列数据类型,不修改列名;且可通过关键字“FIRST”,”AFTER”修改列的位置

ALTER TABLE user
MODIFY sex char(2)

(5)DROP[COLUMN]子句

用于删除列

ALTER TABLE user
DROP sex

(6)RENAME[TO]子句

用于为表重新命名

ALTER TABLE user
RENAME TO userinfo

3重命名表

(1)RENAME TABLE

除了使用上面ALTER TABLE语句,还可直接使用RENAME TABLE语句重命名表

RENAME TABLE tbl_name TO new_tbl_name
[,tbl_name2 TO new_tbl_name2]

4删除表

DROP[TEMPOPARY] TABLE[IF EXISTS]
tbl_name[,tal_name2][,...]

5查看表

(1)显示表名

SHOW[FULL] TABLES [{FROM|IN} db_name]
[LIKE 'pattern'|WHERE expr]

(2)显示表结构

SHOW [FULL] COLUMN {FROM|IN} tbl_name [{FROM|IN} db_name]
[LIKE 'pattern'|WHERE expr]
#或者
{DESCRIBE|DESC} tbl_name [col_name|wild]
#例如
DESC user;
DESC user name

Mysql中IF()函数使用

mysql中if()函数具体语法如下:

IF(expr1,expr2,expr3)
#如果expr1的值为true,则返回expr2的值。
#如果expr1的值为false,则返回expr3的值。

其经常判断查询出来的值,示例;

mysql> select name,if(sex=0,'女','男') as sex from student;
+-------+-----+
| name  | sex |
+-------+-----+
| name1 | 女  |
| name2 | 女  |
| name3 | 男  |
| name4 | 女  |
+-------+-----+

其也经常用到判断的关联条件中,其示例如下:

SELECT  s.SCHOOL_CITY as schoolCity,
        s.SCHOOL_COUNTY as schoolCounty,
        count(DISTINCT `s`.`SCHOOL_ID`) as schoolNum,
        sum(m.duration) as sumDuration,
        sum(`m`.`VIEWERCOUNT`) as viewLiveSum,
        sum(m.replayViewerCount)as reViewSum,
        sum(m.praisecount) as sumpraise,
        sum(`m`.`VIEWERCOUNT`+m.replayViewerCount) as viewSum
         from ((tbl_hbb_mobile_live_statistics m join tbl_hbb_resource_visit_map v) join tbl_school_info s)
    where`m`.`RESOURCEID`= `v`.`RESOURCEID` 
        and if((`v`.`rangeTYPE`= '2'),(`v`.`rangeID`= `s`.`SCHOOL_ID`),(`v`.`parentId`= `s`.`SCHOOL_ID`))

转载至:https://www.cnblogs.com/zjdxr-up/p/8383609.html

Mysql用户变量@

用户变量

可以先在用户变量中保存值留待以后引用,可以将值从一个语句中传递到另一个语句;用户变量和连接有关,所以客户端连接断开后自动销毁。
用户变量的形式为@var_name,其中变量名var_name可以由当前字符集的文字数字字符、‘.’、‘_’和‘$’组成。 默认字符集是cp1252 (Latin1)。可以用mysqld的–default-character-set选项更改字符集。参见5.10.1节,“数据和排序用字符集”。用户变量名对大小写不敏感。

默认值

没有初始化的用户变量默认为 NULL
如果用户变量分配了一个字符串值,其字符集和校对规则与该字符串的相同。用户变量的可压缩性(coercibility)是隐含的。(即为表列值的相同的可压缩性(coercibility)。

设置用户变量方法

设置用户变量方法1

设置用户变量的一个途径是执行SET语句:

SET @var_name = expr [, @var_name = expr] ...

对于SET,可以使用=或:=作为分配符。分配给每个变量的expr可以为整数、实数、字符串或者NULL值。

设置用户变量方法2

也可以用语句代替SET来为用户变量分配一个值。在这种情况下,分配符必须为:=而不能用=,因为在非SET语句中=被视为一个比较 操作符:

mysql> SET @t1=0, @t2=0, @t3=0;
mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
+----------------------+------+------+------+
| @t1:=(@t2:=1)+@t3:=4 | @t1  | @t2  | @t3  |
+----------------------+------+------+------+
|                    5 |    5 |    1 |    4 |
+----------------------+------+------+------+

用户变量的表达式用法

用户变量可用在表达式中。目前不包括明显需要文字值的上下文中,例如SELECT语句的LIMIT子句,或者LOAD DATA语句的IGNORE number LINES子句。

注释:在SELECT语句中,表达式在发送到客户端后才计算,这说明在HAVING,GROUP BY,ORDER BY 字句中,不能使用包含SELECT列表中所设的变量的表达式。
例如,下面的语句不能按期望工作:

mysql> SELECT (@aa:=id) AS a,(@aa+3) AS b FROM table HAVING b=5;

HAVING子句中引用了SELECT列表中的表达式的别名,使用@aa。不能按期望工作:@aa不包含当前行的值,而是前面所选的行的id值。

一般原则是不要在语句的一个部分为用户变量分配一个值而在同一语句的其它部分使用该变量。可能会得到期望的结果,但不能保证。

设置变量并在同一语句中使用它的另一个问题是变量的默认结果的类型取决于语句前面的变量类型。
下面的例子说明了该点:

mysql> SET @a='test';
mysql> SELECT @a,(@a:=20) FROM tbl_name;

对于该 SELECT语句,MySQL向客户端报告第1列是一个字符串,并且将@a的所有访问转换为字符串,即使@a在第2行中设置为一个数字。执行完SELECT语句后,@a被视为下一语句的一个数字。

要想避免这种问题,要么不在同一个语句中设置并使用相同的变量,要么在使用前将变量设置为0、0.0或者”以定义其类型。

未分配的变量有一个值NULL,类型为字符串


用户变量实践:

编写一个 SQL 查询,查找所有至少连续出现三次的数字。

+----+-----+
| Id | Num |
+----+-----+
| 1  |  1  |
| 2  |  1  |
| 3  |  1  |
| 4  |  2  |
| 5  |  1  |
| 6  |  2  |
| 7  |  2  |
+----+-----+
例如,给定上面的 Logs 表, 1 是唯一连续出现至少三次的数字。

+-----------------+
| ConsecutiveNums |
+-----------------+
| 1               |
+-----------------+

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/consecutive-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:

#方法1 
#连续出现的意味着相同数字的 Id 是连着的,由于这题问的是至少连续出现 
#3 次,我们使用 Logs 并检查是否有 3 个连续的相同数字。
#并添加关键字 DISTINCT ,去除重复元素。
SELECT DISTINCT
    l1.Num AS ConsecutiveNums
FROM
    Logs l1,
    Logs l2,
    Logs l3
WHERE
    l1.Id = l2.Id - 1
    AND l2.Id = l3.Id - 1
    AND l1.Num = l2.Num
    AND l2.Num = l3.Num
#但是以上方法存在一个问题就是,当数据出现物理删除导致ID不连贯的时候会出现异常

#方法2
#使用用户变量,用cnt和pre两个变量来统计
select DISTINCT a.Num ConsecutiveNums from (
    select t.Num,
    @cnt:=IF(@pre=t.Num,@cnt+1,1) cnt,
    @pre:=t.Num pre 
    from Logs t,(select @cnt:=0,@pre:=NULL) b ORDER BY t.Id asc) a
where a.cnt>=3
#满足题意,并解决了数据物理删后ID不连续的问题

MySql 在update中实现子查询

MySql更新语句中,经常会碰到需要使用子查询限定更新范围的情况,但是mysql更新语句是不支持子查询的

#例如这样当使用mysql条件更新时--最先让人想到的写法  
UPDATE user SET isagent=1 WHERE uid IN (SELECT uid FROM user_agent) 

#此语句是错误的,会报错 You can't specify target table 'xxx' for update in FROM

这是因为:

mysql的update的一些特点

1、update 时,更新的表不能在set和where中用于子查询;

2、update 时,可以对多个表进行更新(sqlserver不行);

     如:update ta a,tb b set a.Bid=b.id ,b.Aid=a.id;  

3、update 后面可以做任意的查询,这个作用等同于from;

正确的方式是,例:

#简单的更新语句
UPDATE `user` u SET u.`status`=1 WHERE u.`isagent`='1'

#复杂的更新语句
例子1
update member m,(SELECT * FROM FansRole) r set m.agentlevel=(case r.FanskindID when 1 then 0 else r.FanskindID+2 end),m.`level`=r.FanskindID,m.isagent=1,m.`status`=1,m.agenttime=UNIX_TIMESTAMP(r.RegTime) where m.id=r.UserID
例子2
UPDATE order_mall a,(SELECT order_mall.id FROM `order_mall`,`order_goods` WHERE order_mall.`id`=order_goods.`order_id` AND order_goods.order_status=8 AND order_goods.order_goods_type=3) b 
SET a.`status`=4
WHERE a.id=b.id

Mysql字符串拼接方法

Mysql中字符串连接

SELECT '12'+'32','1abc'+'22','abc'+'3'
#结果为:44,2,3
#并非我们想要的1232,1abc22,abc3
#注:在Mysql中,使用“+”进行字符连接时,mysql会尝试将字段值转换为数字类型(如果转换失败,就当做数字0处理)。如’1abc’+’22′,mysql将“1abc”转成数字1在进行运算;将“abc”当做0处理。

所以在Mysql中要使用函数CONCAT(str1,str2,…)来进行字符串拼接,CONCAT函数支持一个或者多个参数,参数类型可以为字符串类型也可以是非字符串类型,对于非字符串类型的参数MYSQL将尝试将其转化为字符串类型,CONCAT函数会将所有参数按照参数的顺序拼接成一个字符串做为返回值。

SELECT CONCAT('车型:',type,',颜色:',color) FROM car;
#结果:“车型:紧凑,颜色:骚粉”

项目从MySql5.5迁移到MySql5.7 timestamp默认值不能为空问题

今天客户项目从开发环境搬迁到生产环境时,因为mysql版本不一致,导致部分表格无法迁移
具体原因为Mysql默认不允许timestamp设置0000-00-00 00:00:00的默认值
经过一番搜索,得到几种解决方案
最后方便起见
直接把timestamp格式字段默认值改成了2000-01-01 00:00:00

常见的方法为修改mysql配置文件,把NO_ZERO_IN_DATE,NO_ZERO_DATE这两个配置去掉

在my.cnf[mysqld]下添加

sql-mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION 

MySql having用法

Mysql中,where是聚合前筛选条件,用于行列数据进入,不可结合函数使用;而having则是用于聚合后数据的筛选,可以接合函数使用,一般having 跟在group by后面使用。
以下是实际使用:
找出person表中重复的邮箱

#方法1 使用临时表 语句比较复杂
select s.email from (
    select email,count(email) as num from person group by email 
) as s 
where s.num>1
#方法2 使用having
select email from person group by email having count(email)>1

#注意having属于聚合后筛选,应在where后,且放置于order by后面

mysql 关联查询 索引不起作用原因记录

今天联表查询的时候发现,两个表的’openid’都已经加了索引,联表的使用也是用的索引字段,理论上应该能命中索引,但是explain分析索引失效了,导致查询平均时间从0.01暴涨到平均十几秒

SELECT l.*,m.nickname,m.id AS member_id,m.mobile,m.avatar,m.realname,m.weixin,m1.nickname AS m1_nickname,m1.id AS m1_id,m1.mobile AS m1_mobile,m1.avatar AS m1_avatar,m1.realname AS m1_realname,m2.nickname AS m2_nickname,m2.id AS m2_id,m2.mobile AS m2_mobile,m2.avatar AS m2_avatar,m2.realname AS m2_realname,ml.logno,ml.createtime AS rechargetime,ml.rechargetype FROM `ims_vcshop_reward` l LEFT JOIN `ims_vcshop_member` m ON l.openid=m.openid LEFT JOIN `ims_vcshop_member` m1 ON l.m1=m1.id LEFT JOIN `ims_vcshop_member` m2 ON l.m2=m2.id LEFT JOIN `ims_vcshop_member_log` ml on ml.id=l.logid WHERE l.uniacid=2  ORDER BY l.id DESC limit 0,50

修改后命中索引

最后通过百度大法发现
1、两表关联使用的条件字段中字段的长度是否是一致的(本人测试不影响,规范期间数据库相同字段还是要保持长度一致)

2、两表关联使用的条件字段中字段的编码是否是一致的

如果以上两种情况不满足,也会导致索引失效;
本人在此就是’openid’字段,分别使用了utf8和utf8mb4两种编码,导致索引失效;

Mysql 5.7 5.6 5.5新增保留字

Mysql5.6新增保留字

GET IO_AFTER_GTIDS IO_BEFORE_GTIDS
MASTER_BIND ONE_SHOT PARTITION
SQL_AFTER_GTIDS SQL_BEFORE_GTIDS

Mysql5.7新增保留字

ACCOUNT ALWAYS CHANNEL
COMPRESSION ENCRYPTION FILE_BLOCK_SIZE
FILTER FOLLOWS GENERATED (R)
GROUP_REPLICATION INSTANCE JSON
MASTER_TLS_VERSION NEVER OPTIMIZER_COSTS (R)
PARSE_GCOL_EXPR PRECEDES REPLICATE_DO_DB
REPLICATE_DO_TABLE REPLICATE_IGNORE_DB REPLICATE_IGNORE_TABLE
REPLICATE_REWRITE_DB REPLICATE_WILD_DO_TABLE REPLICATE_WILD_IGNORE_TABLE
ROTATE STACKED STORED (R)
VALIDATION VIRTUAL (R) WITHOUT
XID