关于日期连续显示问题
问题描述:
我用的SQL server2000
数据库中有一个表:DAYPRODUCT
表中有一个日期字段:date
假如我要取3月1日到3月22日之间的数据,总共是22天
但这之间有些天数据库中没有记录:比方说3月14日 3月21日
但我想在做报表时 按时间升序排列即为:从3月1日到3月22日
对于没有记录的那两天,我想让他在报表中显示为0
报表的最终形式应为这样
时间 交易量
2008-03-01 500
2008-03-02 700
2008-03-03 550
。。。 。。。
2008-03-14 0
。。。 。。。
这个应该怎么样做啊
谢谢,大家指导一下,给点意见
[解决办法]
这样的话 我估计你还要判断一下
就是大月31天 小月30天 润月28天 。。。 。。。
sql吗 有些难写。通过程序还是可以实现的。
[解决办法]
确实很难,因为没有一张表保存了连续的日期,让sql造出两个缺失的日期很困难。
建议你从数据库中select出来以后,在程序中遍历结果的时候补足差值。
[解决办法]
i agree
[解决办法]
要么用程序作,要么用存储过程,要么用临时表
比如临时表,把3月1日到3月22日之间是22天日期存入
select a.日期, (case when a.日期 is null then 0 else a.交易量 end) from DAYPRODUCT a ritht join 临时表 b on a.日期 = b.日期
[解决办法]
告诉你一个实现方法:
就是拼sql。
1、首先算出某月的天数。如,1月31天。
2、StringBuffer sb = new StringBuffer();
sb.append("select isnull((select 时间,交易量 from table where 时间='2008-03-01''),'0')");//先取3月1日的数据
3、然后循环剩余天数,假如还剩30天
for(int i=1;i<13;i++){
sb.append("union all select isnull((select 时间,交易量 from table where 时间='i'),'0')");//获取剩余天数
}
4、最后执行此sql即可。
[解决办法]
漏洞百出啊,忘了c1增加了
...Statememt stmt = yourConnection.createStatement(ResultSet.TYPE_FORWARD_ONLY);ResutSet rs = stmt.executeQuery("select 时间,交易量 from 表 where convert(时间, char(10), 112) between '2008-03-01' and '2008-03-22' order by 时间"); //convert的参数不是112就是120,忘了,好久没用SQLServer,LZ自己查一下帮助Calendar c1 = new GregorianCalendar(2008, 2, 1);Calendar c2 = new GregorianCalendar(2008, 2, 22);Map<String, Integer> map = new HashMap<String, Integer>();//SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");String s1="", s2="";int v = 0;while (c1.before(c2) == false) { s1 = String.format("%1$tF", c1.getTime()); if (s1.equals(s2)) { map.put(s2, v); continue; } if (rs.next()) { s2 = String.format("%1$tF", rs.getDate("时间")); //时间为null字段应该没有吧,重复的时间如果有的话以下要修改,这里以不重复处理 v = rs.getInt("交易量"); if (s1.equals(s2)) { map.put(s2, v); } else if (s1.compareTo(s2) < 0) { //s1>s2的可能没有吧,按LZ的数据 map.put(s1, 0); } } else { map.put(s1, 0); } c1.add(Calendar.Date, 1);}for (Map.Entry<String, Integer> entry : map.entrySet()) { System.out.printf("%s, %d", entry.getKey(), entry.getValue());}...
[解决办法]
给你提供个思路,先生成一张你想要的日期段的表,然后用这张表去LEFT JOIN 你真正的数据表,按日期字段进行关联即可
DECLARE @t TABLE ( Times DATETIME)DECLARE @starttiem DATETIME,@endtime DATETIME SELECT @starttiem = '2009-03-01', @endtime ='2009-03-22' WHILE @starttiem <= @endtime BEGIN INSERT INTO @t SELECT @starttiem SET @starttiem = CONVERT(VARCHAR(10),Dateadd(DAY,1,@starttiem),120) ENDselect * from @t
[解决办法]
生成时间基表,左连即可。
DECLARE @st DATETIME,@et DATETIME,@n INTSELECT @st='2009-3-1',@et='2009-3-22',@n =DATEDIFF(dd,'2009-3-1','2009-3-22') + 1 SET ROWCOUNT @nSELECT ID=IDENTITY(INT),dt = CAST(NULL AS DATETIME) INTO #1 FROM sysobjects,syscolumnsUPDATE #1 SET dt = DATEADD(dd,ID-1,@st)SET ROWCOUNT 0SELECT a.dt,ISNULL(sm,0) 交易量 FROM #1 aLEFT JOIN ( SELECT CONVERT(VARCHAR(10),[date],120) dtYMD,SUM(交易量) sm FROM DAYPRODUCT WHERE [date] >=@st AND [date]<DATEADD(dd,1,@et) GROUP BY CONVERT(VARCHAR(10),[date],120) ) b ON b.dtYMD = dtDROP TABLE #1
[解决办法]
可以做个报表的封装类
import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;/** * 统计报表数据容器 * * @param <R> 行名类型 * @param <C> 列名类型 * * @since 2009-4-28 上午10:41:48 */public class Report<R, C> { /** * 报表容器 */ private Map<R, Map<C, Long>> data = new LinkedHashMap<R, Map<C, Long>>(); /** * 总计 */ private Map<C, Long> total; /** * 列名 */ private List<C> columnNames; /** * 构造方法 * @param rowNames 行名集 * @param columnNames 列名集 */ public Report(R[] rowNames, C[] columnNames) { this(Arrays.asList(rowNames), Arrays.asList(columnNames)); } public Report(R[] rowNames, Collection<C> columnNames) { this(Arrays.asList(rowNames), columnNames); } public Report(Collection<R> rowNames, C[] columnNames) { this(rowNames, Arrays.asList(columnNames)); } public Report(Collection<R> rowNames, Collection<C> columnNames) { this.columnNames = new ArrayList<C>(columnNames); init(rowNames, columnNames); } /** * 根据行名、列名存放数据 * @param rowName * @param columnName * @param count * * @since 2009-4-28 上午10:42:15 */ public void addData(R rowName, C columnName, Long count) { Map<C, Long> row = data.get(rowName); row.put(columnName, row.get(columnName) + count); total.put(columnName, total.get(columnName) + count); } public void addData(R rowName, C columnName, Integer count) { addData(rowName, columnName, count.longValue()); } public List<C> getColumnNames() { return columnNames; } public Map<C, Long> getTotal() { return total; } public Map<R, Map<C, Long>> getData() { return data; } /** * 初始化数据报表 * @param rowNames * @param columnNames * * @since 2009-4-28 上午10:43:53 */ private void init(Collection<R> rowNames, Collection<C> columnNames) { for(Iterator<R> i = rowNames.iterator(); i.hasNext(); ) { data.put(i.next(), generateRow(columnNames)); } total = generateRow(columnNames); } /** * 初始化报表中的一行 * @param columnNames * @return * * @since 2009-4-28 上午10:43:32 */ private Map<C, Long> generateRow(Collection<C> columnNames) { Map<C, Long> row = new LinkedHashMap<C, Long>(); for(Iterator<C> i = columnNames.iterator(); i.hasNext(); ) { row.put(i.next(), 0L); } return row; }}
[解决办法]
create table DAYPRODUCT(id int identity,date smalldatetime,quantity int)
insert DAYPRODUCT
select '2008-3-10',1000
union all
select '2008-3-11',1001
union all
select '2008-3-12',1002
union all
select '2008-3-13',1003
union all
select '2008-3-14',1004
union all
select '2008-3-15',1005
declare @reportDate smalldatetime
set @reportDate='2008-3-1'
;with product as(select date,quantity from DAYPRODUCT where date between @reportDate and dateadd(mm,1,@reportDate)-1)
select * from product
union all
select date,0 quantity from (select top 31 @reportDate+ row_number() over(order by colid)-1 date from syscolumns) tmp
where date<dateadd(mm,1,@reportDate) and not exists(select 1 from product where date=tmp.date)
order by date
drop table DAYPRODUCT
------解决方案--------------------
改一下,这样写更合理点
create table DAYPRODUCT(id int identity,date smalldatetime,quantity int)insert DAYPRODUCTselect '2008-3-10',1000union allselect '2008-3-11',1001union allselect '2008-3-12',1002union allselect '2008-3-13',1003union allselect '2008-3-14',1004union allselect '2008-3-15',1005declare @reportDate smalldatetimeset @reportDate='2008-3-1';with product as(select date,quantity from DAYPRODUCT where date between @reportDate and dateadd(mm,1,@reportDate)-1)select t1.date,(case when t2.quantity is null then 0 else t2.quantity end) quantity from (select top 31 @reportDate+ row_number() over(order by colid)-1 date,0 quantity from syscolumns) t1 left join product t2 on t1.date=t2.date and t2.date<dateadd(mm,1,@reportDate) order by datedrop table DAYPRODUCT