SQL查询速度很慢,要怎么才能优化,或者有更好的方法达到查询效果

lining0755 2011-12-07 11:50:33
declare @tyear as int,@tmonth as int
set @tyear=2011
set @tmonth=10
select
distinct convert(varchar(10), c.checktime, 120) as mydate,
u.userid,u.name,
(select
convert(varchar(5), min(checktime), 108)
from
checkinout
where
convert(varchar(10), checktime, 120)=convert(varchar(10), c.checktime, 120)
and
userid=u.userid) as mintime,
(select
convert(varchar(5), max(checktime), 108)
from
checkinout where convert(varchar(10), checktime, 120)=convert(varchar(10), c.checktime, 120)
and userid=u.userid) as maxtime
from
checkinout as c,userinfo as u
where
c.checktime between '2011-11-01' and '2011-11-30'

order by
mydate


表的关系:
userinfo:
NAME USERID
刘一 1
周二 2
李三 3
徐四 4
王五 5
邹六 6
黄七 7
林八 8
易九 9
蔺十 10


checkinout:
CHECKTIME USERID
2011-11-1 8:25 1
2011-11-1 17:33 1
2011-11-1 8:31 2
2011-11-1 17:42 2
2011-11-1 8:26 4
2011-11-1 19:50 4
2011-11-1 8:25 5
2011-11-1 17:32 5
2011-11-1 8:26 7
2011-11-1 17:32 7

2011-11-2 13:57 3
2011-11-2 17:48 3
2011-11-2 8:26 4
2011-11-2 18:51 4
2011-11-2 8:26 5
2011-11-2 17:30 5
2011-11-2 8:27 6
2011-11-2 18:34 6
2011-11-2 8:26 7
2011-11-2 19:49 7
2011-11-2 8:28 8


2011-11-3 8:27 3
2011-11-3 18:47 3
2011-11-3 8:10 4
2011-11-3 17:36 4
2011-11-3 8:28 7
2011-11-3 17:38 7
2011-11-3 8:24 8
2011-11-3 17:31 8


查询结果如下:
MYDATE NAME MINTIME MAXTIME
2011-11-1 刘一 8:25 17:33
2011-11-1 周二 8:31 17:42
2011-11-1 李三 NULL NULL
2011-11-1 徐四 8:26 19:50
2011-11-1 王五 8:25 17:32
2011-11-1 邹六 NULL NULL
2011-11-1 黄七 8:26 17:32
2011-11-1 林八 NULL NULL
2011-11-1 易九 NULL NULL
2011-11-1 蔺十 NULL NULL

2011-11-2 刘一 NULL NULL
2011-11-2 周二 NULL NULL
2011-11-2 李三 13:57 17:48
2011-11-2 徐四 8:26 18:51
2011-11-2 王五 8:26 17:30
2011-11-2 邹六 8:27 18:34
2011-11-2 黄七 8:26 19:49
2011-11-2 林八 8:28 8:28
2011-11-2 易九 NULL NULL
2011-11-2 蔺十 NULL NULL

2011-11-3 刘一 NULL NULL
2011-11-3 周二 NULL NULL
2011-11-3 李三 8:27 18:47
2011-11-3 徐四 8:10 17:36
2011-11-3 王五 NULL NULL
2011-11-3 邹六 NULL NULL
2011-11-3 黄七 8:28 17:38
2011-11-3 林八 8:24 17:31
2011-11-3 易九 NULL NULL
2011-11-3 蔺十 NULL NULL
...全文
267 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
lining0755 2011-12-08
  • 打赏
  • 举报
回复
楼上的正解,查询速度快了很多
正解:
SQL:
一、
select a.dt,a.name,max(convert(varchar(5),b.checktime,108))maxtime,min(convert(varchar(5),b.checktime,108))mintime
from (
select distinct convert(varchar(10),a.checktime,120)dt,b.userid,b.name from checkinout a,userinfo b
)a left join checkinout b on a.dt=convert(varchar(10),b.checktime,120) and a.userid=b.userid
group by a.dt,a.name
order by a.dt desc

ACCESS:
一、
select a.dt,a.name,format(min(b.checktime),"hh:mm") AS intime, format(max(b.checktime),"hh:mm") AS outtime
from (
select distinct format(a.checktime,"YYYY-MM-DD") AS dt,b.userid,b.name from checkinout a,userinfo b
)a left join checkinout b on a.dt=format(b.checktime,"YYYY-MM-DD") and a.userid=b.userid
group by a.dt,a.name
order by a.dt desc
-晴天 2011-12-08
  • 打赏
  • 举报
回复
select a.dt,a.name,max(convert(varchar(5),b.checktime,108))maxtime,min(convert(varchar(5),b.checktime,108))mintime
from (
select distinct convert(varchar(10),a.checktime,120)dt,b.userid,b.name from checkinout a,userinfo b
)a left join checkinout b on a.dt=convert(varchar(10),b.checktime,120) and a.userid=b.userid
group by a.dt,a.name
order by 1
/*
dt name maxtime mintime
---------- ---------- ------- -------
2011-11-01 黄七 17:32 08:26
2011-11-01 李三 NULL NULL
2011-11-01 林八 NULL NULL
2011-11-01 蔺十 NULL NULL
2011-11-01 刘一 17:33 08:25
2011-11-01 王五 17:32 08:25
2011-11-01 徐四 19:50 08:26
2011-11-01 易九 NULL NULL
2011-11-01 周二 17:42 08:31
2011-11-01 邹六 NULL NULL
2011-11-02 黄七 19:49 08:26
2011-11-02 李三 17:48 13:57
2011-11-02 林八 08:28 08:28
2011-11-02 蔺十 NULL NULL
2011-11-02 刘一 NULL NULL
2011-11-02 王五 17:30 08:26
2011-11-02 徐四 18:51 08:26
2011-11-02 易九 NULL NULL
2011-11-02 周二 NULL NULL
2011-11-02 邹六 18:34 08:27
2011-11-03 黄七 17:38 08:28
2011-11-03 李三 18:47 08:27
2011-11-03 林八 17:31 08:24
2011-11-03 蔺十 NULL NULL
2011-11-03 刘一 NULL NULL
2011-11-03 王五 NULL NULL
2011-11-03 徐四 17:36 08:10
2011-11-03 易九 NULL NULL
2011-11-03 周二 NULL NULL
2011-11-03 邹六 NULL NULL
警告: 聚合或其他 SET 操作消除了空值。

(30 行受影响)

*/
wei779563235 2011-12-07
  • 打赏
  • 举报
回复
从跟底下优化吧。
SQL777 2011-12-07
  • 打赏
  • 举报
回复
declare @tyear as int,@tmonth as int
set @tyear=2011
set @tmonth=10
select
mydate,
u.userid,u.name,
mintime,
maxtime
from
userinfo as u ,
(
select
userid,
convert(varchar(10), c.checktime, 120) as mydate,
convert(varchar(5), min(checktime), 108) mintime,
convert(varchar(5), max(checktime), 108) maxtime
from
checkinout
where
checktime between '2011-11-01' and '2011-11-30'
GROUP BY userid
)T

where T.userid=u.userid

order by mydate
gogodiy 2011-12-07
  • 打赏
  • 举报
回复
checkinout表left join表就行了。
totola147 2011-12-07
  • 打赏
  • 举报
回复
关于优化 你可以吧 操作的顺序 修改一下 执行convert 操作 是为了显示出你想要的结果
但是如果你为了要将显示的结果 转换成喜欢的格式 就对全表的数据执行该操作的话 自然会慢了 所以
将 处理的次序调整一下 先不换 显示的样式 是否满意 先通过查询语句将 想要的那部分记录集 查询出来 比如说 2011-10-1至2011-10-31日之间的数据 这个数据集是一个子集 然后在对它执行转换格式的操作 我想一定会飞一般的快的
totola147 2011-12-07
  • 打赏
  • 举报
回复

declare @tyear as int,@tmonth as int
set @tyear=2011
set @tmonth=10
select
mydate,
u.userid,u.name,
mintime,
maxtime
from
userinfo as u
left outer join
(
select
userid,
convert(varchar(10), c.checktime, 120) as mydate,
convert(varchar(5), min(checktime), 108) mintime,
convert(varchar(5), max(checktime), 108) maxtime
from
checkinout
where
checktime between '2011-11-01' and '2011-11-30'
GROUP BY userid
)T
on T.userid=u.userid

order by mydate
totola147 2011-12-07
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 lining0755 的回复:]
引用 1 楼 sql777 的回复:
SQL code
declare @tyear as int,@tmonth as int
set @tyear=2011
set @tmonth=10
select
mydate,
u.userid,u.name,
mintime,
maxtime
from
userinfo as u ,
(
select
userid, ……
……
[/Quote]
为什么大家都用 convert?? 你的不是 SQL SERVER??
如果是的话 用 year()和month()函数就可以得到 时间中最大的 年份和月份
其次
你要写成 select * from a, b 的形式
按照你给的查询结果来看 是内连接 自然不会显示那些没有考勤记录的同志

你想要 null的效果 要改成外连接
如下形式
select * from a left outer join b on a.x=b.x 将你上面的语句改为这个形式 就会显出人员表里所有的信息 对应的没有考勤记录的 就会置空 !(不是现实字母NULL) 如果你看着这个形式不会套用的话 在回复我就好 我可以帮你改一下 我想你应该会的!

至于查询优化 如果可以用year month 函数的话 自然算是优化了 必经直接当做时间去操作其中的数字 比操作字符快 而且省去了转换和截取 但是如果没有这两个函数可用的话 我也没有什么可以优化查询的办法 因为查询优化 不是我现在可以做的 超出我能力范围了 勿责
lining0755 2011-12-07
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 sql777 的回复:]
SQL code
declare @tyear as int,@tmonth as int
set @tyear=2011
set @tmonth=10
select
mydate,
u.userid,u.name,
mintime,
maxtime
from
userinfo as u ,
(
select
userid, ……
[/Quote]

这样还是不行,得出的结果只有在checkinout有记录的数据,没有记录的不会显示
--小F-- 2011-12-07
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 sql777 的回复:]
SQL code

declare @tyear as int,@tmonth as int
set @tyear=2011
set @tmonth=10
select
mydate,
u.userid,u.name,
mintime,
maxtime
from
userinfo as u ,
(
select
userid……
[/Quote]
支持1楼的做法 还可以把子查询放入临时表

T.userid u.userid字段加索引。

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧