原文:在论坛中出现的比较难的sql问题:3(row_number函数 分组查询)


最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了。

所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路。另外,考虑到前2篇太长,看起来不太方便,所以拆分为第3篇

1、分组查询问题

http://bbs.csdn.net/topics/390619682?page=1#post-395835328

例子表结构数据如下:

id status date        price

1  1      2013-10-01  218

2  1      2013-10-02  218

3  0      2013-10-03  218

4  0      2013-10-04  238

5  0      2013-10-05  238

6  0      2013-10-06  238

7  0      2013-10-07  258

8  0      2013-10-08  258

9  0      2013-10-09  218

想获取的结果集一:

2013-10-01至2013-10-03  218

2013-10-04至2013-10-06  238

2013-10-07至2013-10-08  258
2013-10-09至2013-10-09  218

想获取的结果集二:

1  2013-10-01至2013-10-02  218

0  2013-10-03至2013-10-03  218

0  2013-10-04至2013-10-06  238

0  2013-10-07至2013-10-08  258

0  2013-10-09至2013-10-09  218

我的解法:


  1. --drop table tb
  2. create table tb(id int,status int,date varchar(10),price int)
  3. insert into tb
  4. select 1, 1, '2013-10-01', 218 union all
  5. select 2, 1, '2013-10-02', 218 union all
  6. select 3, 0, '2013-10-03', 218 union all
  7. select 4, 0, '2013-10-04', 238 union all
  8. select 5, 0, '2013-10-05', 238 union all
  9. select 6, 0, '2013-10-06', 238 union all
  10. select 7, 0, '2013-10-07', 258 union all
  11. select 8, 0, '2013-10-08', 258 union all
  12. select 9, 0, '2013-10-09', 218 --union all
  13. --select 10, 0, '2013-10-10', 218
  14. go
  15. --第一个结果集
  16. ;with t
  17. as
  18. (
  19. select *,
  20. row_number() over(partition by price order by id) as rownum,
  21. min(id) over(partition by price) as min_id
  22. from tb
  23. ),
  24. tt
  25. as
  26. (
  27. select id,
  28. price,
  29. a.date,
  30. rownum - (id - min_id) as interval
  31. from t a
  32. )
  33. select min(date) + '至' + max(date) as date,
  34. price
  35. from tt
  36. group by price,interval
  37. order by 1
  38. /*
  39. date price
  40. 2013-10-01至2013-10-03 218
  41. 2013-10-04至2013-10-06 238
  42. 2013-10-07至2013-10-08 258
  43. 2013-10-09至2013-10-09 218
  44. */
  45. --第2个结果集
  46. ;with t
  47. as
  48. (
  49. select *,
  50. row_number() over(partition by status,price order by id) as rownum,
  51. min(id) over(partition by status,price) as min_id
  52. from tb
  53. ),
  54. tt
  55. as
  56. (
  57. select id,
  58. price,
  59. a.date,
  60. a.status,
  61. rownum - (id - min_id) as interval
  62. from t a
  63. )
  64. select status,min(date) + '至' + max(date),price
  65. from tt
  66. group by status,price,interval
  67. order by 2
  68. /*
  69. status date price
  70. 1 2013-10-01至2013-10-02 218
  71. 0 2013-10-03至2013-10-03 218
  72. 0 2013-10-04至2013-10-06 238
  73. 0 2013-10-07至2013-10-08 258
  74. 0 2013-10-09至2013-10-09 218
  75. */

2、查询出一段数据后判断记录里面的最大id,是否大于值a 查询语句如下:
http://bbs.csdn.net/topics/390619191

select top 200 id, ClassId,Name,Price,BoxContain,BoxLength,BoxWidth,BoxHeight,CName,EName,CPack,PhotoFolder,EPack,0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08 from ProductData where ClassId=101 and BoxContain >0 and BoxContain is not null and round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) >=0 And round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) <= 10000 and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) >=10 and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) <=1000 and EPack='Window Box' order by id asc

我的解法,适用于SQL Server 2000:


  1. select *
  2. from
  3. (
  4. select top 200 id, ClassId,Name,Price,BoxContain,BoxLength,BoxWidth,BoxHeight,CName,EName,CPack,PhotoFolder,EPack,
  5. 0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08
  6. from ProductData
  7. where ClassId=101 and BoxContain >0 and BoxContain is not null
  8. and round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) >=0
  9. And round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) <= 10000
  10. and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) >=10
  11. and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) <=1000
  12. and EPack='Window Box'
  13. order by id asc
  14. )t
  15. where
  16. (
  17. select max(id)
  18. from
  19. (
  20. select top 200 id, ClassId,Name,Price,BoxContain,BoxLength,BoxWidth,BoxHeight,CName,EName,CPack,PhotoFolder,EPack,
  21. 0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08
  22. from ProductData
  23. where ClassId=101 and BoxContain >0 and BoxContain is not null
  24. and round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) >=0
  25. And round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3) <= 10000
  26. and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) >=10
  27. and (0.46*(round(((convert(decimal(10,2),BoxLength)*convert(decimal(10,2),BoxWidth) * convert(decimal(10,2),BoxHeight))/1000000),3))*35.32/BoxContain+Price/6*1.08) <=1000
  28. and EPack='Window Box'
  29. order by id asc
  30. )t
  31. ) > a

发布了416 篇原创文章 · 获赞 135 · 访问量 94万+

04-28 05:33