hibernate(HQL)中如何实现对一个字符串字段内容进行分割?如:表中有一个varchar字段,其中一条记录内容:34,23,12,342,23,212,432,34,343,434,3,2,3,4,12,312,3,12,31212,23,23,12,23,21,27,45,34,23假如我想查出这个字段所有记录中第3个逗号的那个整数(12)之和(与其它记录相加中的第3个逗号对应数相加),或者第N个逗号的那个整数之和,请问有没有Hibernate自带函数可以解决?或者调用数据库(MySQL)本地函数解决?业务是这样的:我现在在做一个类似彩票的游戏,这个游戏中玩家可以对 0 - 27 这28个数进行投注,程序会一期一期(期号)随机出现 0 - 27 中任意一个数,程序就需要记录下每个玩家每期的对这 0 - 27 每个数的投注情况,还需要计算赔率(如对“3”这个数投注,那就要把所有玩家对所有数字投注的总和除以所有玩家在“3”这个数字上投注的总和),我的解决方案是把单个玩家对这28个数投注情况做成一个由“,”分割的字段,如果对找出所有玩家在“3”这个数字上投注的总和,就必须分割出第 3 个逗号前面的那个投注数,否则我就要对投注表做31个字段,28个字段记录对这个数的投注情况,1个主键字段,1个期号字段,1个用户ID字段。请HQL高手解决一下。

解决方案 »

  1.   

    可以写存储过程,substring(str,1,2)按下标取出数字,作为临时表字段(用子查询做为临时表也可以),然后 sum或count 一下该字段;要不切成数组计算;要不在Java代码中计算也行
      

  2.   

    java肯定不行,上千个用户使用List性能低,我想在Hibernate中完全解决。如果要是存储过程的话,Hibernate没有多大意义了。
      

  3.   

    要么是写存储过程在数据库中 截取和操作后返回
    要么查询出来 在java中进行遍历操作 
    个人觉得放在数据库方 会好些
      

  4.   


    存储过程这个我知道,但是已经使用了Hibernate封装,我还是希望尽量避免
    存储过程。
      

  5.   

    select SUM(SUBSTRING(column ,len))from table;应该可以吧?
      

  6.   

    呃SUBSTRING()少写个参数...要在column后面加个起始位置.
      

  7.   


    呵呵,你再认真读一下我的业务需求,len这个长度你是没办法确定的。
      

  8.   

    直接使用本地查询,createSQLQuery()
      

  9.   


    嗯,这方法不错,但是,在用户表中的点数字段我设置的是bigint型,谁也说不好以后用户的点数能存多少,如果要是标准化,每个注长度*28+27,那这个注长度要设多少为标准化呢,这个彩注字段是varchar类型的,会不会有超出的情况呢?
      

  10.   

    觉得表结构设计不合理,而且hibernate本身设计就不太容易写一些比较复杂的sql。
    建议修改表结构,主键,期号,用户id,所选号码,投注钱数
    虽然数据量会很大,但是你3分钟开一次,按照你原来的表结构数据量也小不了
      

  11.   

    SUBSTRING_INDEX(`字段`,'分隔符','index')其中index表示你想要的数据,例如3,取到12
      

  12.   

    用存储过程来做,循环、SUBSTR()、INSTR()就可以做出来了
      

  13.   

    这个使用hql怕是有难度,可以在mysql中自定义一个split函数得到指定位置的分隔字串并把它转为数字并用sum函数进行统计,具体可以参照这篇文章:http://apps.hi.baidu.com/share/detail/16244647
      

  14.   


    这个是Hibernate封装的数库访问。
      

  15.   


    非常感谢,但是我既然用了HQL,就不希望在数据库里写一些自定义函数和存储过程了,这些我之前也考虑过了。
      

  16.   

    ---------楼主资料---------
    登录名:hswzyx
    总技术分:87
    总技术排名:121234
    ---------结贴情况---------
    截至:2010-12-07 04:28:26
    总发帖:5个
    正常结贴:0个
    未结贴:2
    结贴率:60.00%
    评语:楼主,说真的你的结贴率不高哇!
    --------------------------
      

  17.   

    可以写存储过程,substring(str,1,2)按下标取出数字,作为临时表字段(用子查询做为临时表也可以),然后 sum或count 一下该字段;要不切成数组计算;要不在Java代码中计算也行
      

  18.   

    话说看了许久,看明白需求了。你就是想找到指定的位置的数字之和,是吧?但是据我所知(也可能是我开发经验少),还是没有见过hibernate有那么类似的函数的。。只能找另外的方法,再帮楼主想想,想不出的别见怪
      

  19.   

    取出第三个数:substring_index(substring_index(name, ',', 3),',',-1)
    其他的lz应该能搞定吧
      

  20.   


    Hibernate既然封装了数据库访问,写存储过程还是比较不妥的,我希望还是尽量在HQL中完成。
      

  21.   


    嗯,谢谢,26楼那个朋友的方法可以试试,SUBSTRING_INDEX(`字段`,'分隔符','index'),大家共勉。
      

  22.   


    那这种方法需要在java中实现,估计性能会降低很多,如果能在MySQL中直接筛出来的话最好。
      

  23.   

    HQL和SQL差不多一样的,HQL也可以用SQL中的函数!想分割,Spilt还是可以的!
      

  24.   

    lz的表设计有问题,字符串截来截去非常耗cpu和内存,做出来也没法玩啊,当然你说要28个字段的那个设计也有问题。
    你看这样设计表行不行1个主键字段,1个期号字段,1个用户ID字段,1个投注值字段(就是你在投注字段数字上投了多少),1个投注数字(只能是0-27)
    现在要求某个投注数字的和只要select sum(投注值字段) from table1 group by 投注数字建议lz看看数据库原理,讲三个范式的那段
      

  25.   


    不会的,所有工作都交给java做,性能肯定会降低。比如其中有个业务是取得中奖人数(比如中奖结果是3,就要将对当前期号投注的所有用户的投注记录中第3个逗号前的那个数不为零的提取出来),同时还要计算赔率(中奖结果同上,就要将对当前期号投注的所有用户的投注记录中第3个逗号前的不为零的数进行相加除以奖池的总数),这两个业务是在一起的。
      

  26.   


    呵呵,那也是自定义函数,还是希望尽量在HQL语句中实现。
      

  27.   

    感觉HQL做出这种东西来很困难啊。。楼主还是考虑考虑其他办法吧
      

  28.   


    嗯,是,HQL不能提供更灵活的函数,我再考虑一下,如果要是把投注分成28个字段,这样会不会好一些,各位有什么意见吗?
      

  29.   

    仔细看了一下你方案,你的数据库表设计肯定是有问题的,首先,你用带“,”号的字符串来存用户的投注,数据冗余比较大,因为用户不可能每个数都投注,你里面的“,”号和0完全是增加了数据库的存储量,第二就是采用字符串运算来检索数据库不可能使用索引,必然得全库扫描每一条记录,检索效率极低,随着数据量的增大,用户等待时间将大幅增加,从而失去了程序的可操作性。建议还是设计成几个表要好:开奖表(id,期号,开奖类型,开奖时间,开奖状态,中奖号码)、投注表(id,开奖id,玩家id,投注号码,投注点数)、玩家表(id,登陆名,口令......),这样做统计是很简单的,在投注表建立了索引的情况下,数据库检索的时间可以节省很多(与索引树的深度有关),至于你考虑的记录数量的问题,如果觉得量大,可以考虑采用oracle、db2等大型数据库,只要优化调整得好,完全可以轻松支撑下来。
      

  30.   

    看了一下你的需求,现在假设你的字段名为column1select SUM(SUBSTRING_INDEX(SUBSTRING_INDEX(column1,',',3),','-1)) from table其中SUBSTRING_INDEX(column1,',',3)取得结果 34,23,12SUBSTRING_INDEX(SUBSTRING_INDEX(column1,',',3),','-1)取得结果 12
    然后经过 sum 这个函数就可以计算了。
    如果还有其它凝问可以加我qq,现在也是正在开发跟楼主相类似的软件。qq :402279001
      

  31.   

    觉得你表设计的的确有问题, 93楼已经给了解法了, 就不多说
    另外如果你真的很在意计算赔率的效率的话, 根本就不需要从数据库里取数据, 建立一个数组, 当每一个彩注被投注的时候, 将彩注对应的元素自增, 向下面这样
    static int[] xx = new int[28]
    比如当彩注3被投注的时候 xx[3]++
    然后赔率  = xx[3]/sum(xx)
      

  32.   

    红的那行改下:比如当彩注3被投注为33的时候 xx[3] = xx[3] + 33
      

  33.   


    谢谢,很感谢。说的非常好。这个游戏不能排除每个用户对每个数字的投注,我之前写那么多的“0,”,就是为了让大家容易看清对哪个数进行了投注。绝不能排除这样的投注:34,23,12,342,23,212,432,34,343,434,3,2,3,4,12,312,3,12,31212,23,23,12,23,21,27,45,34,23
    而且是经常性的,因为这个网站的客户给过我一个参考网站,我看了一下,确实是这样的,很多用户对每个数字进行投注。而且有几种投注方式:全押、押大、押小、押中、押边等,都是对多个数进行投注的。而且后面的“生肖乐”游戏会产生45个数字的投注。这个网站就算有100个用户,每3分钟就可能产生4500条记录。数据库客户那边有要求是MySQL的。检索这部分是要先筛出“期号”、再“找出对应数字的投注数”,如果要是索引的话,也是对期号索引吧?用对投注字段进行索引吗?
      

  34.   

    不错,和captainblue说的一样。但是这个函数是不是需要在Hibernate注册一下。Hibernate应该不支持这个函数吧。我看Hibernate注册函数的源代码里没有这个函数。