记录下SQL笔记,久了没用忘掉了,咳,真TMD郁闷
分组后WHERE用having
SELECT FAge,COUNT(*) AS CountOfThisAge FROM T_Employee GROUP BY FAge HAVING COUNT (*) IN (1,3)
Group by 按需求取得指定数据
SELECT data.* from table as data right join (select max(id) as id from table group by gbfield) as temp on temp.id=data.id
GROUP BY 的时候可以获取用函数获得指定字段的值,通过以上方法可以获取指定结果集 但group by 的字段要做索引,否则效率很低
防止重复数据的产生
SELECT DISTINCT FDepartment FROM T_Employee;
字段间计算
SELECT 125+521 as staticnm,FNumber,FName,FAge * FSalary FROM T_Employee;
字符串处理
SELECT FName, LENGTH(FName) AS namelength FROM T_Employee WHERE FName IS NOT NULL
SELECT FName, SUBSTRING(FName,2,3) FROM T_Employee WHERE FName IS NOT NULL
SELECT CONCAT('年龄:',FAge) FROM T_Employee
结果集联合(需要遵守:一是每个结果集必须有相同的列数;二是每个结果集的列必须类型相容。)
SELECT FNumber,FName,FAge FROM T_Employee UNION SELECT FIdCardNumber,FName,FAge FROM T_TempEmployee
默认情况下,UNION运算符合并了两个查询结果集,需要在联合结果集中返回所有的记录而不管它们是否唯一,则需要在 UNION运算符后使用ALL操作符,比如下面的SQL语句:
SELECT FName,FAge FROM T_Employee UNION ALL SELECT FName,FAge FROM T_TempEmployee
使用UNION的时候各列的顺序最好相同,不然有很多意想不到的结果
MYSQL中使用DATEDIFF()函数用于计算两个日期之间的差额
SELECT FRegDay,FBirthDay, DATEDIFF(FRegDay, FBirthDay) , DATEDIFF(FBirthDay ,FRegDay)FROM T_Person
CASE函数
SELECT FName,
(CASE FName
WHEN 'Tom' THEN 'GoodBoy'
WHEN 'Lily' THEN 'GoodGirl'
WHEN 'Sam' THEN 'BadBoy'
WHEN 'Kerry' THEN 'BadGirl'
ELSE 'Normal'
END) as isgood
FROM T_Person
但字段值为NULL的时候case NULL 无效
该使用
SELECT FName,
if (isnull(isgood),'good','bad') as isgood
FROM T_Person
MYSQL不支持如下,当DB2等数据库支持
一次定义多次使用
WITH person_tom AS
(
SELECT * FROM T_Person
WHERE FName='TOM'
)
SELECT * FROM T_Person
WHERE FAge=person_tom.FAge
OR FSalary=person_tom.FSalary
ANY关键词的意思是“对于在子查询返回的列中的任一数值,如果比较结果为TRUE的话,则返回TRUE”。
有一真为真
SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);
词语IN是=ANY的别名。因此,这两个语句是一样的:
SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 IN (SELECT s1 FROM t2);
词语ALL必须接在一个比较操作符的后面。ALL的意思是“对于子查询返回的列中的所有值,如果比较结果为TRUE,则返回TRUE。”例如:
多个比较
SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2);
SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);
如果在表t2的一个行中,column1=1并且column2=2,则查询结果均为TRUE。
EXISTS和NOT EXISTS
EXISTS (有结果为真 无结果为假) 下个相反
如果一个子查询返回任何的行,则EXISTS subquery为FALSE
子查询结果为单个时候可以直接等于~(小心使用~)
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
正常表达式
select * from xxx where aa regexp 'xxx';
select * from xxx where aa regexp "";
join 将两个表合到一个表进行查询 字段合并 合并条件以on为准
select * from test1 join test2 on test1.a=test2.d
select * from t1 join (t2, t3, t4) on (t1.id=t2.id and t2.id=t3.id and t3.id=t1.id ) #复杂查询
记得跟ON 语句
left join 以左表为基准
right join 以右表为基准
join 两个表都因同时存在记录为基准
链表删除
delete t1 from test1 as t1 join test2 ad t2 on t1.a=t2.a where t2.c='3'
链表更新
update test1 ad t1 join test2 as t2 on t1.a=t2.a set t1.b='100' where t2.c='4';
链表同步
update test1 as t1 join test2 as t2 set t1.b=t2.c where t1.a=t2.a
查询插入
连表分页
select * from (select * from test1 union select * from test2) as temp limit 0,100;
返回一个不同值的数目。
mysql> select COUNT(DISTINCT results) from student;
group by 中字段中使用函数是对汇总子表的操作
汇总并返回平均数
mysql> select student_name, AVG(test_score)
from student
GROUP BY student_name;
链表的时候尽量不要GROUP BY ,是非常缓慢的...
INSTR(str,substr)
返回子串substr在字符串str中的第一个出现的位置。这与有2个参数形式的LOCATE()相同,除了参数被颠倒。
mysql> select INSTR('foobarbar', 'bar');
-> 4
mysql> select INSTR('xbar', 'foobar');
-> 0
LPAD(str,len,padstr)
返回字符串str,左面用字符串padstr填补直到str是len个字符长。
mysql> select LPAD('hi',4,'??');
-> '??hi'
LEFT(str,len)
返回字符串str的最左面len个字符。
mysql> select LEFT('foobarbar', 5);
-> 'fooba'
该函数是多字节可靠的。
RIGHT(str,len)
返回字符串str的最右面len个字符。
mysql> select RIGHT('foobarbar', 4);
-> 'rbar'
该函数是多字节可靠的。
REPEAT(str,count)
返回由重复countTimes次的字符串str组成的一个字符串。如果count <= 0,返回一个空字符串。如果str或count是NULL,返回NULL。
mysql> select REPEAT('MySQL', 3);
-> 'MySQLMySQLMySQL'
LOWER(str)
返回字符串str,根据当前字符集映射(缺省是ISO-8859-1 Latin1)把所有的字符改变成小写。该函数对多字节是可靠的。
mysql> select LCASE('QUADRATICALLY');
-> 'quadratically'
查询插入:
insert into table1 select field21 as field11 ,field22 ad field12 from table2 where file11='test';
查询结果创建一个列并赋值默认值
select *,'test' as newfield from test;
汇总后合并汇总那些行的结果到一行
SELECT g, group_concat( test1 SEPARATOR "-" ) AS bbb FROM a_test GROUP BY g
不一定搭配group by 使用
SELECT g, group_concat( test1 SEPARATOR "-" ) AS bbb FROM a_test
直接把表里指定字段的数据全链接,默认用,链接
除非简单查询,GROUP_CONCAT用于复杂查询将是不可行的
插入更新:ON DUPLICATE KEY UPDATE
条件更新:(非常有用~)
update t2
set b=case
when a<2 then b+1
when a>2 then 0
end
UNIX时间戳转日期格式
select FROM_UNIXTIME(1156219870);
连表join注意:join 的时候会连接一个表,组成新表后在连下一个表,如
SELECT * FROM `a_ta` as ta join a_tc as tc on ta.id=tc.id join a_tb as tb on ta.id=tb.id
先a_ta和a_tc组成一个表,在和a_tb组成一个表
当没有on语句的时候 会由每一个记录来组成一个表,所以查出来的结果是两个表记录的卡迪尔积,
join on 的结果是两个表同时存在记录的那些记录 但ON不能加判断值.
where between a and b;//在字段AB之间
where between 1 and 2;//在1和2之间
行转列
//转自:cnblogs.com/kerrycode
我们首先先通过一个老生常谈的例子,学生成绩表(下面简化了些)来形象了解下行转列
(
[UserName] NVARCHAR(20), --学生姓名
[Subject] NVARCHAR(30), --科目
[Score] FLOAT, --成绩
)
INSERT INTO [StudentScores] SELECT 'Nick', '语文', 80
INSERT INTO [StudentScores] SELECT 'Nick', '数学', 90
INSERT INTO [StudentScores] SELECT 'Nick', '英语', 70
INSERT INTO [StudentScores] SELECT 'Nick', '生物', 85
INSERT INTO [StudentScores] SELECT 'Kent', '语文', 80
INSERT INTO [StudentScores] SELECT 'Kent', '数学', 90
INSERT INTO [StudentScores] SELECT 'Kent', '英语', 70
INSERT INTO [StudentScores] SELECT 'Kent', '生物', 85
如果我想知道每位学生的每科成绩,而且每个学生的全部成绩排成一行,这样方便我查看、统计,导出数据
UserName,
MAX(CASE Subject WHEN '语文' THEN Score ELSE 0 END) AS '语文',
MAX(CASE Subject WHEN '数学' THEN Score ELSE 0 END) AS '数学',
MAX(CASE Subject WHEN '英语' THEN Score ELSE 0 END) AS '英语',
MAX(CASE Subject WHEN '生物' THEN Score ELSE 0 END) AS '生物'
FROM dbo.[StudentScores]
GROUP BY UserName
解释:增加4列,并根据指定行的情况赋值该列,汇总结果并取得指定列的最大值,没有该记录结果就是0
按照IN里的顺序取数据
id in (1,2,3) order by FIELD(id, 1,2,3)
id in (1,2,3) order by substring_index('1,2,3',id,1);
//效率都差不多~
重结果集里获取随机数据
SELECT * FROM ko_channel ORDER BY rand() LIMIT 2
分组结果并获取每条分组中的一个记录
SQL获取两个经纬度距离
6367000*2*ASIN(LEAST(
1,SQRT(
POW( SIN( (RADIANS(X(GEOMFROMTEXT('POINT({$point})'))) - RADIANS(X(location))) /2 ), 2)
+
COS(
RADIANS(X(location))
)
*COS(
RADIANS(X(GEOMFROMTEXT('POINT({$point})')))
)
*POW( SIN( (RADIANS(Y(GEOMFROMTEXT('POINT({$point})'))) - RADIANS(Y(location))) / 2 ), 2 )
)
))
存储过程动态调用存储过程
SET @fn = CONCAT('CALL order_rollback_',buy_type,'(?,?)');
PREPARE stmt1 FROM @fn;
SET @a = id_product;
SET @b = buy_num;
EXECUTE stmt1 USING @a, @b;
DEALLOCATE PREPARE stmt1;
事件
CREATE EVENT order_pay_rollback ON SCHEDULE AT '2016-11-11 11:11:11' ON COMPLETION NOT PRESERVE ENABLE DO CALL order_pay_rollback(11);
存储过程
CREATE PROCEDURE order_pay_rollback(id_order_pay int)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE id_product int;
DECLARE cur1 CURSOR FOR SELECT
id_product as id_product
FROM p
WHERE id_order_pay=id_order_pay ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO id_product;
IF done THEN
LEAVE read_loop;
END IF;
CALL order_rollback(id_product);
END LOOP;
close cur1;
END;