oralce分類統計

@Transactional
@Component("statisDAO")
@Scope("prototype")
public class StatisDAO extends AbstractDAO {
    private static final String SQL_STATIS_CHANNELTYPE = "INSERT INTO channeltypestatis(uuid,counter,channeltype,accountarea,statistime,statisrange) " +
    		"SELECT DBMS_RANDOM.STRING('A', 32) AS uuid, count(*) AS counter, channeltype, accountarea,sysdate AS statistime,to_char(?)||'/'||to_char(?) AS STATISRANGE " +
    		"FROM ACTIVITY WHERE txtime>=? AND txtime<=?  GROUP BY ROLLUP (channeltype,accountarea)";

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean statisChanneltype(String startDateStr,String endDateStr) {
        try {
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date startDate=format.parse(startDateStr+" 00:00:00");
            Date endDate=format.parse(endDateStr+" 23:59:59");
            
            Object[] values = {startDateStr,endDateStr,startDate,endDate};
            this.getSmartDAO().update("", SQL_STATIS_CHANNELTYPE, values);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
public static void main(String[] args) {
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("file:E:\\CommonContext.xml");
        StatisDAO statisDAO = (StatisDAO) applicationContext.getBean("statisDAO");
        System.out.println(statisDAO.statisChanneltype("2011-04-01", "2011-08-02"));
    }

}

按日期時長統計:

 

 


統計每個時間段得條目數,txtime是date類型,sql如下:

按小時---select to_char(txtime, 'YYYY-MM-dd hh24') a,count(*) from mytable group by to_char(txtime,'YYYY-MM-dd hh24');

按天---select to_char(txtime, 'YYYY-MM-dd') a,count(*) from mytable group by to_char(txtime,'YYYY-MM-dd');

按月---select to_char(txtime, 'YYYY-MM') a,count(*) from mytable group by to_char(txtime,'YYYY-MM');


按年---select to_char(txtime, 'YYYY') a,count(*) from mytable group by to_char(txtime,'YYYY');

按季度---select to_char(txtime, 'YYYY-q') a,count(*) from mytable group by to_char(txtime,'YYYY-q');

按周---select to_char(txtime, 'ww') a,count(*) from mytable group by to_char(txtime,'ww');

 

參考http://hi.baidu.com/qq5910225/blog/item/4a8c91d7ef0ec514a08bb74e.html

 

同字符串類型統計

 

select
SUM(CASE
WHEN city = '海口市' THEN
1
ELSE
0
END) haikou_num
,SUM(CASE
WHEN city = '廣州市' THEN
1
ELSE
0
END) guangzhou_num
FROM ACTIVITY_HIS

decode方式

SQL> select id,num from test1;

ID NUM
---------- ----------
1 3
1 4
2 2
2 5
3 1
3 8

6 rows selected

SQL> select decode(grouping(id),1, '總計 ',id) id,sum(num) num
2 from test1
3 group by rollup(id);

ID NUM
---------------------------------------- ----------
1 7
2 7
3 9
總計 23

<!--StartFragment -->

最終大神:select count(*), province, city from ACTIVITY_HIS where to_char(txtime, 'YYYY-MM-dd')='2011-06-01' group by rollup (province,city);

rollup是數據挖掘中的上卷操作,運行效果截圖

 

另外,將取出來得數據直接插入表中:

select ...into 用在存儲過程裏面的,保存變量
insert ...select 就是插入語句,插入的部分是表中的數據

 

舉例來說:

insert 表 select * from 表的方法主要有兩種:

1、若兩張表完全相同:
insert into table1
select * from table2
where condition(條件)

2、若兩張表字段有不同的:
insert into table1(字段1,字段2,字段3....)
select 字段1,字段2,字段3....
from table2
where condition(條件)

上述兩種方法均不需要寫values.

綜上,我的sql是:

INSERT INTO channeltypestatis(uuid,counter,channeltype,accountarea,statistime,statisrange)

SELECT DBMS_RANDOM.STRING('A', 32) AS uuid, count(*) AS counter, channeltype, accountarea,sysdate AS statistime,TO_CHAR(?,'yyyy-mm-dd') AS STATISRANGE

FROM ACTIVITY

WHERE where to_char(txtime, 'yyyy-mm-dd')>'?' AND TO_CHAR(txtime, 'yyyy-mm-dd')<'?'

GROUP BY ROLLUP (channeltype,accountarea)

 

channeltypestatis數據字典:

CHANNELTYPESTATIS UUID VARCHAR2
CHANNELTYPESTATIS COUNTER NUMBER
CHANNELTYPESTATIS CHANNELTYPE VARCHAR2
CHANNELTYPESTATIS ACCOUNTAREA VARCHAR2
CHANNELTYPESTATIS STATISTIME DATE
CHANNELTYPESTATIS STATISRANGE VARCHAR2

 

在編寫過程中還有問題:

 

代碼片段

@Transactional
@Component("statisDAO")
@Scope("prototype")
public class StatisDAO extends AbstractDAO {
    private static final String SQL_STATIS_CHANNELTYPE = "INSERT INTO channeltypestatis(uuid,counter,channeltype,accountarea,statistime,statisrange) SELECT DBMS_RANDOM.STRING('A', 32) AS uuid, count(*) AS counter, channeltype, accountarea,sysdate AS statistime,TO_CHAR(?/?) AS STATISRANGE FROM ACTIVITY WHERE txtime>=to_date(?, 'yyyy-mm-dd') AND txtime<=to_date(?, 'yyyy-mm-dd')  GROUP BY ROLLUP (channeltype,accountarea)";

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean statisChanneltype(String startDate,String endDate) {
        try {
            Object[] values = {startDate,endDate,startDate,endDate};
            this.getSmartDAO().update("", SQL_STATIS_CHANNELTYPE, values);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static void main(String[] args) {
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("file:E:\\CommonContext.xml");
        StatisDAO statisDAO = (StatisDAO) applicationContext.getBean("statisDAO");
        System.out.println(statisDAO.statisChanneltype("2011-04-01", "2011-08-02"));
    }
}

 

如果 報無效的列索引,原因是在sql語句中 ?不能加' 而應如上所示

 

但上述代碼依舊報錯,錯誤的數字格式,因爲是我傳 2011-08-02 參數的時候,解析sql時,會產生錯誤,最終改成了如下格式

 

@Transactional
@Component("statisDAO")
@Scope("prototype")
public class StatisDAO extends AbstractDAO {
    private static final String SQL_STATIS_CHANNELTYPE = "INSERT INTO channeltypestatis(uuid,counter,channeltype,accountarea,statistime,statisrange) SELECT DBMS_RANDOM.STRING('A', 32) AS uuid, count(*) AS counter, channeltype, accountarea,sysdate AS statistime,TO_CHAR(?-?) AS STATISRANGE FROM ACTIVITY WHERE txtime>=to_date(?, 'yyyymmdd') AND txtime<=to_date(?, 'yyyymmdd')  GROUP BY ROLLUP (channeltype,accountarea)";

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean statisChanneltype(String startDate,String endDate) {
        try {
            Object[] values = {startDate,endDate,startDate,endDate};
            this.getSmartDAO().update("", SQL_STATIS_CHANNELTYPE, values);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static void main(String[] args) {
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("file:E:\\CommonContext.xml");
        StatisDAO statisDAO = (StatisDAO) applicationContext.getBean("statisDAO");
        System.out.println(statisDAO.statisChanneltype("20110401", "20110802"));
    }
}

 

但是TO_CHAR(?-?) 這個函數給我解析成數學符號後,全給我相減了NND,應該用oracle中的字符串拼接。其他常用oracle函數見下一篇

 

帶拼接的,還應注意時間,前面的不能滿足當天查詢

 

@Transactional
@Component("statisDAO")
@Scope("prototype")
public class StatisDAO extends AbstractDAO {
    private static final String SQL_STATIS_CHANNELTYPE = "INSERT INTO channeltypestatis(uuid,counter,channeltype,accountarea,statistime,statisrange) " +
    		"SELECT DBMS_RANDOM.STRING('A', 32) AS uuid, count(*) AS counter, channeltype, accountarea,sysdate AS statistime,to_char(?)||'/'||to_char(?) AS STATISRANGE " +
    		"FROM ACTIVITY WHERE txtime>=? AND txtime<=?  GROUP BY ROLLUP (channeltype,accountarea)";

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean statisChanneltype(String startDateStr,String endDateStr) {
        try {
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date startDate=format.parse(startDateStr+" 00:00:00");
            Date endDate=format.parse(endDateStr+" 23:59:59");
            
            Object[] values = {startDateStr,endDateStr,startDate,endDate};
            this.getSmartDAO().update("", SQL_STATIS_CHANNELTYPE, values);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

public static void main(String[] args) {
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("file:E:\\CommonContext.xml");
        StatisDAO statisDAO = (StatisDAO) applicationContext.getBean("statisDAO");
        System.out.println(statisDAO.statisChanneltype("2011-08-01", "2011-08-01"));
    }

}
 

 

 

但是上述sql語句是採用SELECT DBMS_RANDOM.STRING('A', 32)隨機數的,這個是可能相同的,因此要求使用sequence,但是sequence和group by一塊使用會報錯:ORA-02287: 此處不允許序號,

INSERT INTO channeltypestatis(uuid,counter,channeltype,accountarea,statistime,statisrange) 
SELECT SEQ_PK.nextVal as uuid , count(*) AS counter, channeltype, accountarea,sysdate AS statistime,to_char('2011-08-01')||'/'||to_char('2011-08-01') AS STATISRANGE FROM ACTIVITY 
WHERE txtime>=to_date('2011-08-01 00:00:00','yyyy-mm-dd hh24:mi:ss') AND txtime<=to_date('2011-08-01 23:59:59','yyyy-mm-dd hh24:mi:ss')  GROUP BY ROLLUP (channeltype,accountarea)

報錯:oracle sequence ORA-02287: 此處不允許序號

採用

INSERT INTO channeltypestatis(uuid,counter,channeltype,accountarea,statistime,statisrange) 
SELECT SEQ_PK.nextVal as uuid , P.* from 
(select count(*) AS counter, channeltype, accountarea,sysdate AS statistime,to_char('2011-08-01')||'/'||to_char('2011-08-01') AS STATISRANGE 
FROM ACTIVITY WHERE txtime>=to_date('2011-08-01 00:00:00','yyyy-mm-dd hh24:mi:ss') AND txtime<=to_date('2011-08-01 23:59:59','yyyy-mm-dd hh24:mi:ss')  GROUP BY ROLLUP (channeltype,accountarea)) P
 

 

進行使用即可

最終代碼爲:

 

 

@Transactional
@Component("statisDAO")
@Scope("prototype")
public class StatisDAO extends AbstractDAO {
    private static final String SQL_STATIS_CHANNELTYPE ="INSERT INTO channeltypestatis(uuid,counter,channeltype,accountarea,statistime,statisrange) " +
    		"SELECT SEQ_PK.nextVal as uuid , P.* from " +
    		"(select count(*) AS counter, channeltype, accountarea,sysdate AS statistime,to_char(?)||'/'||to_char(?) AS STATISRANGE " +
    		"FROM ACTIVITY WHERE txtime>=? AND txtime<=? " +
    		"GROUP BY ROLLUP (channeltype,accountarea)) P";

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean statisChanneltype(String startDateStr,String endDateStr) {
        try {
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date startDate=format.parse(startDateStr+" 00:00:00");
            Date endDate=format.parse(endDateStr+" 23:59:59");
            
            Object[] values = {startDateStr,endDateStr,startDate,endDate};
            this.getSmartDAO().update("", SQL_STATIS_CHANNELTYPE, values);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
    
}

 

哎,又有新問題出現了,當用rollup進行統計時,如果原有數據中有null,在所有時它統計也過也是null於是就杯具了,如同第一個圖,經過搜索

 

將上述sql更改爲

INSERT INTO channeltypestatis(uuid,counter,channeltype,accountarea,statistime,statisrange) 
SELECT SEQ_PK_CHANNELTYPESTATIS.nextVal as uuid , P.* from    
(select count(*) AS counter, Decode(Grouping(channeltype),1,'所有渠道',channeltype) channeltype,Decode(Grouping(accountarea),1,'所有地區',accountarea) accountarea,sysdate AS statistime,to_char('2011-08-01')||'/'||to_char('2011-08-01') AS STATISRANGE    
FROM ACTIVITY WHERE txtime>=to_date('2011-08-01 00:00:00','yyyy-mm-dd hh24:mi:ss') AND txtime<=to_date('2011-08-01 23:59:59','yyyy-mm-dd hh24:mi:ss')  GROUP BY ROLLUP (channeltype,accountarea)) P   

 

即可,其中搜索出的結果如圖2所示

 

問題還在:就是accountarea區域不能就合計,就是不能求得北京的all值,因此sql再次修改爲

 

INSERT INTO channeltypestatis(uuid,counter,channeltype,accountarea,statistime,statisrange) 

SELECT SEQ_PK_CHANNELTYPESTATIS.nextVal AS uuid , P.* FROM
(SELECT count(*) AS counter, Decode(Grouping(channeltype),1,'ALL',channeltype) channeltype,Decode(Grouping(accountarea),1,'ALL',accountarea) accountarea,sysdate AS statistime,to_char('2011-08-01')||'/'||to_char('2011-08-01') AS STATISRANGE 
FROM activity WHERE txtime>=to_date('2011-04-01','yyyy-mm-dd') AND txtime<=to_date('2011-08-01','yyyy-mm-dd')
GROUP BY CUBE (channeltype,accountarea)) P

 

注意將rollup換成了cube即可,關於cube和rollup的區別詳見:

http://space.itpub.net/519536/viewspace-610997

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章