请教一个sql

junnyfeng 2009-10-21 04:17:11
有一个记录罪犯资料的表 casetalbe
结构如下:
idcard char(20) --罪犯的id
case_type char(1) -- 0 刑事案件 --1 民事案件
case char(400) --犯罪记录
case_date date --犯罪时间

现在要选出idcard, case_type, case, case_date, 如果一个罪犯有多条犯罪记录,只显示发生最早的那一条。



+--------+-----------+----------+------------+
| idcard | case_type | case | case_date |
+--------+-----------+----------+------------+
| 12345 | 0 | 抢劫 | 1998-01-28 |
| 12345 | 0 | 吸毒 | 2003-03-04 |
| 12345 | 0 | 抢劫 | 2003-03-04 |
| 12345 | 1 | 欠钱不还 | 2004-03-04 |
| 34555 | 1 | 欠钱不还 | 2004-08-18 |
| 66665 | 1 | 欠钱不还 | 2005-11-07 |
+--------+-----------+----------+------------+



最终结果应该是12345那个罪犯的两个抢劫只显示1998年的那个抢劫

...全文
147 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
daiyan_2008 2009-10-23
  • 打赏
  • 举报
回复


select * from casetable where case_time in (select min(case_time) from casetable group by idcard);

daiyan_2008 2009-10-23
  • 打赏
  • 举报
回复

select * from casetable where case_time in (select min(case_time) from casetable group by idcard);


我是新人,不知道对不对,进来练习下...
wwwwb 2009-10-23
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 junnyfeng 的回复:]
哦,有做时间判断,看错了,但不太理解它的做法。
[/Quote]
这是一个自连接查询,实际上你可以执行
select a.idcard,a.case_type,a.case,a.case_date,b.* from tt a
left join tt b on a.idcard=b.idcard and a.case_date>=b.case_date

看看结果就知道了,你可以测试一下,HAVING与EXISTS的速度对比如何
junnyfeng 2009-10-22
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 acmain_chm 的回复:]
引用哦,有做时间判断,看错了,但不太理解它的做法。
这个做法原理是把这个表本身做了次笛卡尔积,以条例 a.case_date>=b.case_date 这样找出所以对应比当前记录中日期小记录。再做group 后取这having count(b.case_date)=1;

这个SQL的做法效率很差。
[/Quote]


a.case_date>=b.case_date ,它select出来的是a.case_date,应该是选出大的那个时间才对吧,
2003-03-04 不是大于 1998-01-28 ?
test119 2009-10-22
  • 打赏
  • 举报
回复
只有这两种么
[Quote=引用 2 楼 vinsonshen 的回复:]
SQL codeselect a.*from casetalbe awherenotexists (select1from casetalbe bwhere b.idcard=a.idcardand b.case_type=a.case_typeand b.case=a.caseand b.case_date<a.case_date);
[/Quote]貌似这个效率也不高。。。等于遍历两遍表吧?
ACMAIN_CHM 2009-10-22
  • 打赏
  • 举报
回复
[Quote]哦,有做时间判断,看错了,但不太理解它的做法。[/Quote]
这个做法原理是把这个表本身做了次笛卡尔积,以条例 a.case_date>=b.case_date 这样找出所以对应比当前记录中日期小记录。再做group 后取这having count(b.case_date)=1;

这个SQL的做法效率很差。
vinsonshen 2009-10-22
  • 打赏
  • 举报
回复
对了,你的相关字段都建立了合适索引了吗?
那试下这个吧:

select a.* 
from
casetalbe a,
(select idcard,case_type,case,min(case_date) as min_date from casetalbe group by idcard,case_type,case) b
where b.idcard=a.idcard and b.case_type=a.case_type and b.case=a.case and b.min_date=a.case_date);

平凡的思想者 2009-10-22
  • 打赏
  • 举报
回复
更简单的写法,转换成unix时间进行排序更快:
select idcard,case_type,case,case_date
from casetalbe
group by idcard,case_date
order by unix_timestamp(case_date)
limit 1

平凡的思想者 2009-10-22
  • 打赏
  • 举报
回复
更简单的写法:
select idcard,case_type,case,case_date
from casetalbe
group by idcard,case_date
order by case_date
limit 1
junnyfeng 2009-10-21
  • 打赏
  • 举报
回复
哦,有做时间判断,看错了,但不太理解它的做法。
junnyfeng 2009-10-21
  • 打赏
  • 举报
回复
1楼的稍微改一下是正确的,但很神奇,它没有对时间做判断,居然出来的结果会是时间最早的那条,请问有人能解释一下吗? 还有,left join 一般什么情况下使用的?

mysql> select a.idcard,a.case_type,a.casem,a.case_date from casetable a
-> left join casetable b on
-> a.idcard=b.idcard
-> and a.case_type = b.case_type
-> and a.casem = b.casem
-> and a.case_date>=b.case_date
-> group by a.idcard,a.case_type,a.casem,a.case_date having count(b.case_date)=1;
+--------+-----------+----------+------------+
| idcard | case_type | casem | case_date |
+--------+-----------+----------+------------+
| 12345 | 0 | ÇÀ½Ù | 1998-01-28 |
| 12345 | 0 | Ç¿¼é | 2003-03-04 |
| 12345 | 1 | Ç·Ç®²»»¹ | 2004-03-04 |
| 34555 | 1 | Ç·Ç®²»»¹ | 2004-08-18 |
| 66665 | 1 | Ç·Ç®²»»¹ | 2005-11-07 |
+--------+-----------+----------+------------+
5 rows in set (0.00 sec)
junnyfeng 2009-10-21
  • 打赏
  • 举报
回复
验证后,2楼的正确,4楼的那个好理解,但写得不完整,应该是这样:

select a.* from casetable a,
(select idcard,case_type,casem,min(case_date)case_date from casetable group by idcard,case_type,casem ) b
where a.idcard = b.idcard
and a.case_type = b.case_type and
a.casem = b.casem and
a.case_date = b.case_date;

+--------+-----------+----------+------------+
| idcard | case_type | casem | case_date |
+--------+-----------+----------+------------+
| 12345 | 0 | ÇÀ½Ù | 1998-01-28 |
| 12345 | 0 | Ç¿¼é | 2003-03-04 |
| 12345 | 1 | Ç·Ç®²»»¹ | 2004-03-04 |
| 34555 | 1 | Ç·Ç®²»»¹ | 2004-08-18 |
| 66665 | 1 | Ç·Ç®²»»¹ | 2005-11-07 |
+--------+-----------+----------+------------+
5 rows in set (0.00 sec)


vinsonshen 2009-10-21
  • 打赏
  • 举报
回复
从楼主给的记录需求看,应该不但是以idcard来区分,还要以case来区分的:
+--------+-----------+----------+------------+
| idcard | case_type | case | case_date |
+--------+-----------+----------+------------+
| 12345 | 0 | 抢劫 | 1998-01-28 |
| 12345 | 0 | 吸毒 | 2003-03-04 |
| 12345 | 0 | 抢劫 | 2003-03-04 |
| 12345 | 1 | 欠钱不还 | 2004-03-04 |
| 34555 | 1 | 欠钱不还 | 2004-08-18 |
| 66665 | 1 | 欠钱不还 | 2005-11-07 |
+--------+-----------+----------+------------+

最终结果应该是12345那个罪犯的两个抢劫只显示1998年的那个抢劫

猜搂主针对上面的源数据想要的结果是:
+--------+-----------+----------+------------+
| idcard | case_type | case | case_date |
+--------+-----------+----------+------------+
| 12345 | 0 | 抢劫 | 1998-01-28 |
| 12345 | 0 | 吸毒 | 2003-03-04 |
| 12345 | 1 | 欠钱不还 | 2004-03-04 |
| 34555 | 1 | 欠钱不还 | 2004-08-18 |
| 66665 | 1 | 欠钱不还 | 2005-11-07 |
+--------+-----------+----------+------------+
junnyfeng 2009-10-21
  • 打赏
  • 举报
回复

fdfasfd
junnyfeng 2009-10-21
  • 打赏
  • 举报
回复
select * from tt
nianzhang747 2009-10-21
  • 打赏
  • 举报
回复
现在要选出idcard, case_type, case, case_date, 如果一个罪犯有多条犯罪记录,只显示发生最早的那一条。



+--------+-----------+----------+------------+
| idcard | case_type | case | case_date |
+--------+-----------+----------+------------+
| 12345 | 0 | 抢劫 | 1998-01-28 |
| 12345 | 0 | 吸毒 | 2003-03-04 |
| 12345 | 0 | 抢劫 | 2003-03-04 |
| 12345 | 1 | 欠钱不还 | 2004-03-04 |
| 34555 | 1 | 欠钱不还 | 2004-08-18 |
| 66665 | 1 | 欠钱不还 | 2005-11-07 |
------------------------------------------------------------
select * from t ,(select idcard,min(case_date) from t group by idcard ) tt
where t.idcard = tt.idcard
ACMAIN_CHM 2009-10-21
  • 打赏
  • 举报
回复
select * from casetalbe a 
where not exists (select 1 from casetalbe where idcard=a.idcard and case_date<a.case_date);
vinsonshen 2009-10-21
  • 打赏
  • 举报
回复
select a.* from casetalbe a 
where not exists (select 1 from casetalbe b where b.idcard=a.idcard and b.case_type=a.case_type and b.case=a.case and b.case_date<a.case_date);
WWWWA 2009-10-21
  • 打赏
  • 举报
回复
select a.idcard,a.case_type,a.case,a.case_date from tt a
left join tt b on a.idcard=b.idcard and a.case_date>=b.case_date
group by a.idcard,a.case_type,a.case,a.case_date having count(b.case_date)=1

56,675

社区成员

发帖
与我相关
我的任务
社区描述
MySQL相关内容讨论专区
社区管理员
  • MySQL
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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