2014-10-10 528 views
4

我有以下表格租赁(book_date,copy_id,member_id,title_id,act_ret_date,exp_ret_date)。 book_date显示预订的那天。我需要为每个月的每一天写一个查询(从1-30或1-29或1-31或每个月的数据),它会显示预订的书籍数量。
我现在知道如何显示在表中的在天租书的数量
SQL查询一个月中的所有天数

select count(book_date), to_char(book_date,'DD') 
from rental 
group by to_char(book_date,'DD'); 

我的问题是:

  1. 如何显示的余生(如果让我们说出于某种原因,在我的数据库中,我没有20日或19日或多天租用的书籍),并将数字0放在那里?
  2. 我该如何显示当前月份的天数(28,29,30,31这4个月都可能取决于月份或年份)......我迷路了。这必须只使用SQL查询没有pl/SQL或其他的东西。
+1

请添加标签,指明您正在使用的数据库平台。 – 2014-10-10 12:58:54

+0

使用一个日历表,然后用租赁表执行'LEFT JOIN' – Lamak 2014-10-10 12:59:43

+0

你说PL/SQL没有,你在Oracle吗? – MPelletier 2014-10-10 13:00:27

回答

3

下面的查询会给你所有天当月,你的情况,你可以用你的日期列替换SYSDATE并加入这个查询知道有多少给定月份

SELECT DT 
FROM(
SELECT TRUNC (last_day(SYSDATE) - ROWNUM) dt 
    FROM DUAL CONNECT BY ROWNUM < 32 
) 
    where DT >= trunc(sysdate,'mm') 
+0

非常感谢jafar这是我需要解决我的问题的部分,非常感谢! – 2014-10-10 13:25:00

+1

你缺少+1(TRUNC(last_day(SYSDATE) - ROWNUM)+ 1)。一个较短的版本将是:SELECT TRUNC(last_day(TO_DATE('201708','YYYYMM')) - ROWNUM + 1)dat FROM DUAL CONNECT BY ROWNUM njank 2017-09-29 05:10:39

1

答案就是创建这样一个表:

表yearsmonthsdays(年VARCHAR(4),月VARCHAR(2),天VARCHAR(2));

使用您希望的任何语言,例如在Java中使用Calendar.getInstance()。getActualMaximum(Calendar.DAY_OF_MONTH)迭代以获取月份的最后一天,并根据需要填充多年和月份,并填充表格,其中包含从1到最后一天的年,月和日你的结果的月份。

你会得到这样的:

insert into yearsmonthsdays ('1995','02','01'); 
insert into yearsmonthsdays ('1995','02','02'); 
... 
insert into yearsmonthsdays ('1995','02','28'); /* non-leap year */ 
... 
insert into yearsmonthsdays ('1996','02','01'); 
insert into yearsmonthsdays ('1996','02','02'); 
... 
insert into yearsmonthsdays ('1996','02','28'); 
insert into yearsmonthsdays ('1996','02','29'); /* leap year */ 
... 

等。

完成此表后,您的工作即将完成。在表格和此表格之间进行外部左连接,将年,月和日连接在一起,并且不显示任何行时,计数将根据您的意愿为零。没有使用编程,这是你最好的选择。

+0

谢谢路易斯,但它似乎是双我所需要的:D – 2014-10-10 13:34:15

+0

我写这之前,我知道它是甲骨文 - 这种解决方案是更多的数据库不可知论者。 – 2014-10-11 16:05:17

1

中,您可以从dual进行查询并使用conncect by level语法生成一系列行 - 在您的情况下为日期。从那里,它只是一个决定的事要显示(在我的例子中,我使用所有的日期从2014年起),并加入你的桌子上什么日期:

SELECT all_date, COALESCE (cnt, 0) 
FROM  (SELECT to_date('01/01/2014', 'dd/mm/yyyy') + rownum - 1 AS all_date 
      FROM dual 
      CONNECT BY LEVEL <= 365) d 
LEFT JOIN (SELECT TRUNC(book_date), COUNT(book_date) AS cnt 
      FROM  rental 
      GROUP BY book_date) r ON d.all_date = TRUNC(r.book_date) 
+0

谢谢您的关注@Mureinik。你的回答也让我解决了我的问题。我不是很擅长解释我需要什么。非常感谢你 ! – 2014-10-10 13:33:48

0

有没有必要让ROWNUM参与......你可以只使用LEVELCONNECT BY

WITH d1 AS (
    SELECT TRUNC(SYSDATE, 'MONTH') - 1 + LEVEL AS book_date 
     FROM dual 
    CONNECT BY TRUNC(SYSDATE, 'MONTH') - 1 + LEVEL <= LAST_DAY(SYSDATE) 
) 
SELECT TRUNC(d1.book_date), COUNT(r.book_date) 
    FROM d1 LEFT JOIN rental r 
    ON TRUNC(d1.book_date) = TRUNC(r.book_date) 
GROUP BY TRUNC(d1.book_date); 

只需将SYSDATE替换为您定位结果的月份中的日期即可。