常用内置函数
Oracle
-- greatest :两列中取更晚的时间
select greatest(time1,time2) as time from Test;
-- concat :字符串拼接,只支持两个参数,Mysql为三个
select * from Test where name like concat('%','3');--可用 || 代替
-- replace :字符串替换,三个参数
select replace(id,'1','2') from Test;--id中的1替换为2
-- ifnull :若为空,替换为
select ifnull(id,'unknown') from Test;--id中的null替换为unknown
-- instr :根据in排序
SELECT * FROM Test where id in ('1','2') ORDER BY instr('1,2',id );
-- start with * onnect by * :树结构遍历
select * from TestA start with id='1' connect by pid = prior id ;
SqlServer
元数据信息
select t.name column_name,COLUMNPROPERTY( t.id, t.name, 'PRECISION' ) data_length,
isnull( COLUMNPROPERTY( t.id, t.name, 'Scale' ), 0 ) numeric_scale, b.name data_type,
pk = CASE WHEN EXISTS ( SELECT 1 FROM sysobjects WHERE xtype = 'PK' AND parent_obj = t.id
AND name IN ( SELECT name FROM sysindexes
WHERE indid IN ( SELECT indid FROM sysindexkeys WHERE id = t.id AND colid = t.colid ) ) )
THEN'1' ELSE '0' END,
t.isnullable nullable,CONVERT(nvarchar(200),ISNULL(g.[value], ''))
as comments from syscolumns t
inner join sys.objects f on t.id = f.object_id
left join sys.schemas s on s.schema_id = f.schema_id
left join systypes b on t.xusertype=b.xusertype
left join sys.extended_properties g on g.name = 'MS_Description' and t.id=g.major_id and t.colid=g.minor_id
where s.name = 'dbo'
MySQL
-- Mysql版层级查询(根据id查所有子节点的信息)(id,pid)
create function getChildren(val varchar(64))
returns varchar(4000)
begin
declare oTemp varchar(4000);
declare oTempChild varchar(4000);
set oTemp = "";
set oTempChild = val;
while oTempChild is not null
do
set oTemp = concat(oTemp,',',otempchild);
select group_concat(id) into oTempChild from TestA where find_in_set(pid,oTempChild)>0;
end while ;
return oTemp;
END;
--
select * from TestA where find_in_set(xlh,getChildren('4'));
性能
-- 锁时间TOP10
SELECT DIGEST_TEXT, SUM_LOCK_TIME FROM
performance_schema.events_statements_summary_by_digest ORDER BY SUM_LOCK_TIME DESC LIMIT 10
-- 平均响应时间TOP10
SELECT DIGEST_TEXT,AVG_TIMER_WAIT FROM
performance_schema.events_statements_summary_by_digest ORDER BY AVG_TIMER_WAIT DESC LIMIT 10;
-- 排序记录数TOP10
SELECT DIGEST_TEXT,SUM_SORT_ROWS FROM
performance_schema.events_statements_summary_by_digest ORDER BY SUM_SORT_ROWS DESC LIMIT 10;
-- 扫描记录数TOP10
SELECT DIGEST_TEXT,SUM_ROWS_EXAMINED FROM
performance_schema.events_statements_summary_by_digest ORDER BY SUM_ROWS_EXAMINED DESC
LIMIT 10;
-- 创建临时表TOP10
SELECT DIGEST_TEXT,SUM_CREATED_TMP_TABLES,SUM_CREATED_TMP_DISK_TABLES FROM
performance_schema.events_statements_summary_by_digest ORDER BY SUM_CREATED_TMP_TABLES DESC
LIMIT 10
查看执行记录
set GLOBAL general_log = 'ON'
SELECT * from mysql.general_log ORDER BY event_time DESC;
kill
SELECT * FROM information_schema.PROCESSLIST where length(info) >0 ;
kill 742862
连接查询和子查询
-- 子查询(可以用于echarts的柱状图统计中),这样的查询效率更低,最好使用join
select a.name,
(select b.b from TestB b where b.id = a.id)
from TestA a
-- left join + group by
SELECT COUNT(A.ID) AS NUM ,B.NAME AS NAME from A
LEFT JOIN B ON A.ID = B.ID
GROUP BY B.NAME
避免使用Not IN 和 IN
-- A是B的子表,查出所有无效的子表数据
SELECT * FROM A WHERE A.TID NOT IN (SELECT ID FROM B) -- in是一种相关子查询,子查询会被循环执行
-- 使用 NOT EXISTS 替代
SELECT * FROM A WHERE NOT EXISTS (SELECT B.ID FROM B WHERE A.TID =B.ID )-- exists是非相关子查询,子查询先执行且只执行一次
分组后按某个字段取出其中一行数据
Oracle
SELECT * FROM (
SELECT TYPE,CREATE_TIME,ROW_NUMBER() OVER (PARTITION BY TYPE ORDER BY CREATE_TIME DESC) rn
FROM TABLE1 ) t WHERE t.rn = 1 -- 根据type分组然后取出每组create_time最晚的那条数据
MySQL
SELECT A.CREATE_TIME,A.TYPE from
(SELECT * FROM TABLE1 ORDER BY CREATE_TIME DESC limit 10000 ) A GROUP BY A.TYPE
-- 根据type分组然后取出每组create_time最晚的那条数据
-- 为什么要加limit:Mysql在5.5.28以上子查询中使用order by其结果不会显示排序后的结果,而是被自动优化排序,所以需要加limit,但是limit的上限为10000
一个审批流程问题记录
问题
现有任务表和任务详情表,用来保存审批流程 其数据结构简写如下: TASK { id,desc} TASK_DETAIL { id,tid,name,seq,state } 后者的seq是审批顺序,从1开始,tid关联task.id,state保存审批状态:1 已审批,0未审批. name为审批人的姓名 现在需要根据name 来查找出所有自己待审批的任务desc.
思路
待审批的任务:流程前的人都已经审批通过或者流程第一个人待审批的合计. 所以隐藏条件就是,seq-1的那条数据的状态是已通过.
select a.tid from task_detail a inner join
(select tid,(seq-1)as seq from task_detail where state = 0 and name = 'NameTest') b
on a.tid = b.tid and a.seq = b.seq
where a.state = 1
union all
select tid from task_detail where seq = 1 and state = 0 and name = 'NameTest'