Date range union
Hi!
I have a subscription system, where people can subscribe to a publication during a certain period of time. I would like to know how long a person has subscribed to any publication, so i wonder does anyone know how to perform a "date range union"? By that, i mean that a query on this data:
with test_data as (select 1 id, to_date('01-JAN-2000','DD-MON-YYYY') start_date, to_date('27-JUN-2003','DD-MON-YYYY') stop_date from dual union
select 2, to_date('05-APR-2003','DD-MON-YYYY'), to_date('04-JAN-2004','DD-MON-YYYY') from dual union
select 3, to_date('03-JUL-2002','DD-MON-YYYY'), to_date('02-JUL-2008','DD-MON-YYYY') from dual)
select * from test_data;
should produce
START_DATE STOP_DATE
01-JAN-2000 00:00:00 02-JUL-2008 00:00:00
So there can be any number of periods, and they can overlap entirely as well as "on one end".
I have solved this using PL/SQL, but would like to know if there is a SQL solution. I have also solved this with a fixed number of periods (2,3...) but not with any number.
Sorry my fault. Soon after posting I found a case when the result was wrong, so I corrected the query (added default value 1 to lag(gap,1) i.e. lag(gap,1,1)) without leaving a notice. I'm home now - no database access - but I can comment to make it easier for you.
select the_start start_date,stop_date
from (
-- propagating the_start value: we keep data ordered by start date
-- we carry the value of the_start from overlap row to the non-overlap row
select start_date,stop_date,gap,
case when gap = 1 and lag(gap,1) over (order by start_date) = 0
then lag(the_start,1) over (order by start_date)
else start_date
end the_start
from (
-- excluding intermediate overlaps: gap = 0 and the_start is null
select start_date,stop_date,gap,the_start
from (
-- identifying start days: we keep data ordered by start date
-- when we have the first overlap (current gap = 0, but the gap on the previous row <> 0) we record the start_date as the_start
select start_date,stop_date,gap,
case when gap = 0 and lag(gap,1,1) over (order by start_date) = 1
then start_date
end the_start
from (
-- identifying period breaks: we keep data ordered by start date
-- when the start_date on the next row is not greater than the stop_date on the current row we have an overlap
select start_date,stop_date,
case when lead(start_date,1) over (order by start_date) <= stop_date
then 0
else 1
end gap
from test_data
where gap = 1 or the_start is not null
where gap = 1
order by start_dateTo check intermediate results run step by step starting from the inner query (just comment out the outer queries). I'm pretty sure LAG, not LEAD
Regards
Etbin
Similar Messages
-
Discoverer Date Range Union Query
Hi All,
I need your help in creating a discovere report in version 11G.
Following Report find missing elimination account based on Transaction done in a date Range. Find out how many accounts are not defined in Elimination Account Setup. Following query gives me desired output but i am having hard time creating a discoverer report for Date Range Parameter as Date Range only applied to one side of union.
In First Query i used decode with sysdate itself so that i can use effective_date as parameter and second side i just kept sysdate.
PLease let me know how can i create a parameterized report for effective_date range.
SELECT
/*+ ORDERED
USE_NL(jel jeh jeb cat src)
INDEX(jel GL_JE_LINES_N1)
INDEX(jeh GL_JE_HEADERS_U1)
INDEX(jeb GL_JE_BATCHES_U1)
INDEX(cat GL_JE_CATEGORIES_TL_U1)
INDEX(src GL_JE_SOURCES_TL_U1) */
CC.SEGMENT1
||'.'
||CC.segment2
||'.'
||CC.segment3
||'.'
||cc.segment4
||'.'
|| cc.segment5
||'.'
|| cc.segment6 Account,
decode(sysdate,sysdate,sysdate,jel.effective_date) trx_date
FROM gl_code_combinations cc,
gl_je_lines jel,
gl_je_headers jeh,
gl_je_batches jeb,
gl_je_categories cat,
gl_je_sources src
WHERE cc.CHART_OF_ACCOUNTS_ID = 50308
AND cc.segment2 IN ('111710','201910')
AND jel.code_combination_id = cc.code_combination_id
AND jel.status
|| '' = 'P'
AND (jel.accounted_cr != 0
OR jel.accounted_dr != 0)
AND jeh.je_header_id = jel.je_header_id
AND jeh.actual_flag = 'A'
AND jeh.currency_code != 'STAT'
AND jeb.je_batch_id = jeh.je_batch_id
AND jeb.average_journal_flag = 'N'
AND src.je_source_name = jeh.je_source
AND cat.je_category_name = jeh.je_category
and jel.effective_date between to_date('01-JAN-2011','DD-MON-RRRR') and to_date('31-MAY-2011','DD-MON-RRRR')
MINUS
SELECT (source_segment1
||'.'
||source_segment2
||'.'
||source_segment3
||'.'
||source_segment4
||'.'
||source_segment5
||'.'
||source_segment6) def_acnt,
sysdate
FROM GL_ELIM_ACCOUNTS_MAPHi,
You can use the following SQL to get the effective date into the SQL and by that create the condition in the report:
SELECT
CC.SEGMENT1
||'.'
||CC.segment2
||'.'
||CC.segment3
||'.'
||cc.segment4
||'.'
|| cc.segment5
||'.'
|| cc.segment6 Account,
decode(sysdate,sysdate,sysdate,jel.effective_date) trx_date,
jel.effective_date
FROM gl_code_combinations cc,
gl_je_lines jel,
gl_je_headers jeh,
gl_je_batches jeb,
gl_je_categories cat,
gl_je_sources src
WHERE cc.CHART_OF_ACCOUNTS_ID = 50308
AND cc.segment2 IN ('111710','201910')
AND jel.code_combination_id = cc.code_combination_id
AND jel.status
|| '' = 'P'
AND (jel.accounted_cr != 0
OR jel.accounted_dr != 0)
AND jeh.je_header_id = jel.je_header_id
AND jeh.actual_flag = 'A'
AND jeh.currency_code != 'STAT'
AND jeb.je_batch_id = jeh.je_batch_id
AND jeb.average_journal_flag = 'N'
AND src.je_source_name = jeh.je_source
AND cat.je_category_name = jeh.je_category
AND NOT EXISTS (
SELECT 1
FROM GL_ELIM_ACCOUNTS_MAP
WHERE CC.SEGMENT1 = source_segment1
AND CC.segment2 = source_segment2
AND CC.segment3 = source_segment3
AND cc.segment4 = source_segment4
AND cc.segment5 = source_segment5
AND cc.segment6 = source_segment6
AND decode(sysdate,sysdate,sysdate,jel.effective_date) = SYSDATE
*** I removed the hints, but if you need those get them back
*** BTW i didn't understand the logic behind the "decode(sysdate,sysdate,sysdate,jel.effective_date)" wouldn't it always be SYSDATE???
Tamir -
Display of 2 rows of data for 2 different date range selection
Hi Folks,
I have a requirement as follows,
User has an option of selecting 2 Date Ranges
From and To Date and again From and To Date
The result should display 2 different rows of data with From and To Date range selection.
Eg:
12/09/20008 to 03/09/2009 10 20 30 40
23/10/2009 to 18/12/2010 40 20 10 30
Difference 30 0 20 10
% Change x y z q
Thanks for your input.
Regards,
KJYou will need to use union report, and you would have fours union's in this report.
Union - 1: Data from 1st Date Range
Union - 2: Data from 2nd Date Range
Union - 3: Variance Calculation
Union - 4: Percentage Variance Calculation.
If the date's are coming from the same field, use cast function to use the same column twice in your prompts. Apply filters on each union as needed.
Thanks. -
How to get top 11 values per date range
I want to get the top 11 values by date range.
Sample Data
CREATE TABLE SAMPLE_DATA
DOMAIN_NAME VARCHAR2(100),
QTD NUMBER,
LOAD_DATE DATE
-- Insert
BEGIN
FOR lc IN 1..20
LOOP
FOR ld IN 1..30
LOOP
INSERT
INTO SAMPLE_DATA VALUES
'DM_'
||lc,
round(dbms_random.value(0,1000)),
SYSDATE-ld
END LOOP;
END LOOP;
COMMIT;
END;
SELECT *
FROM
(SELECT DOMAIN_NAME,
QTD,
LOAD_DATE
FROM
(SELECT DOMAIN_NAME,
QTD,
LOAD_DATE
FROM SAMPLE_DATA
WHERE LOAD_DATE = TRUNC(SYSDATE-3)
ORDER BY QTD DESC
WHERE ROWNUM <=10
UNION ALL
SELECT 'Others' DOMAIN_NAME,
SUM(QTD) QTD,
LOAD_DATE
FROM
(SELECT DOMAIN_NAME,
QTD,
LOAD_DATE
FROM
(SELECT rownum rn,
DOMAIN_NAME,
QTD,
LOAD_DATE
FROM
(SELECT DOMAIN_NAME,
QTD,
LOAD_DATE
FROM SAMPLE_DATA
WHERE LOAD_DATE = TRUNC(SYSDATE-3)
ORDER BY QTD DESC
WHERE rn > 10
GROUP BY LOAD_DATE
ORDER BY QTD DESC
-- Result
DOMAIN_NAME QTD LOAD_DATE
Others 2888 24/03/13
DM_1 1000 24/03/13
DM_20 933 24/03/13
DM_11 913 24/03/13
DM_3 743 24/03/13
DM_13 572 24/03/13
DM_12 568 24/03/13
DM_9 564 24/03/13
DM_6 505 24/03/13
DM_5 504 24/03/13
DM_2 480 24/03/13
Please, Help me get in one query this result using a range of date.
e.g
using LOAD_DATE BETWEEN '24/03/13' AND '25/03/13'
DOMAIN_NAME QTD LOAD_DATE
Others 2888 24/03/13
DM_1 1000 24/03/13
DM_20 933 24/03/13
DM_11 913 24/03/13
DM_3 743 24/03/13
DM_13 572 24/03/13
DM_12 568 24/03/13
DM_9 564 24/03/13
DM_6 505 24/03/13
DM_5 504 24/03/13
DM_2 480 24/03/13
Others 1948 25/03/13
DM_1 807 25/03/13
DM_8 764 25/03/13
DM_7 761 25/03/13
DM_11 656 25/03/13
DM_18 611 25/03/13
DM_17 523 25/03/13
DM_14 467 25/03/13
DM_19 447 25/03/13
DM_15 437 25/03/13
DM_6 380 25/03/13 Thank you in advance.I got the solution. Just sharing.
I used analytic functions that make my job easy.
Sample Data
DOMAIN_NAME QTD LOAD_DATE
DM_1 807 25/03/2013
DM_1 1000 24/03/2013
DM_2 226 25/03/2013
DM_2 480 24/03/2013
DM_3 244 25/03/2013
DM_3 743 24/03/2013
DM_4 48 25/03/2013
DM_4 413 24/03/2013
DM_5 164 25/03/2013
DM_5 504 24/03/2013
DM_6 380 25/03/2013
DM_6 505 24/03/2013
DM_7 761 25/03/2013
DM_7 212 24/03/2013
DM_8 764 25/03/2013
DM_8 308 24/03/2013
DM_9 354 25/03/2013
DM_9 564 24/03/2013
DM_10 214 25/03/2013
DM_10 367 24/03/2013
DM_11 656 25/03/2013
DM_11 913 24/03/2013
DM_12 37 25/03/2013
DM_12 568 24/03/2013
DM_13 332 25/03/2013
DM_13 572 24/03/2013
DM_14 467 25/03/2013
DM_14 87 24/03/2013
DM_15 437 25/03/2013
DM_15 450 24/03/2013
DM_16 238 25/03/2013
DM_16 299 24/03/2013
DM_17 523 25/03/2013
DM_17 143 24/03/2013
DM_18 611 25/03/2013
DM_18 145 24/03/2013
DM_19 447 25/03/2013
DM_19 464 24/03/2013
DM_20 91 25/03/2013
DM_20 933 24/03/2013 Top 11 QTD of DOMAIN_NAME per Data Range.
SELECT *
FROM
(SELECT DOMAIN_NAME,
QTD,
LOAD_DATE
FROM
(SELECT LOAD_DATE,
DOMAIN_NAME ,
QTD,
(DENSE_RANK() OVER (PARTITION BY LOAD_DATE ORDER BY QTD DESC )) AS RANK_QTD
FROM SAMPLE_DATA
WHERE trunc(load_date) BETWEEN '24/03/2013' AND '25/03/2013'
WHERE RANK_QTD <= 10
UNION ALL
SELECT 'Others',
SUM(QTD) AS QTD,
LOAD_DATE
FROM
(SELECT LOAD_DATE,
DOMAIN_NAME ,
QTD,
(DENSE_RANK() OVER (PARTITION BY LOAD_DATE ORDER BY QTD DESC )) AS RANK_QTD
FROM SAMPLE_DATA
WHERE trunc(load_date) BETWEEN '24/03/2013' AND '25/03/2013'
WHERE RANK_QTD > 10
GROUP BY LOAD_DATE
ORDER BY LOAD_DATE ASC,
QTD DESC
DOMAIN_NAME QTD LOAD_DATE
Others 2888 24/03/2013
DM_1 1000 24/03/2013
DM_20 933 24/03/2013
DM_11 913 24/03/2013
DM_3 743 24/03/2013
DM_13 572 24/03/2013
DM_12 568 24/03/2013
DM_9 564 24/03/2013
DM_6 505 24/03/2013
DM_5 504 24/03/2013
DM_2 480 24/03/2013
Others 1948 25/03/2013
DM_1 807 25/03/2013
DM_8 764 25/03/2013
DM_7 761 25/03/2013
DM_11 656 25/03/2013
DM_18 611 25/03/2013
DM_17 523 25/03/2013
DM_14 467 25/03/2013
DM_19 447 25/03/2013
DM_15 437 25/03/2013
DM_6 380 25/03/2013 -
Continious data range algorithm
I have in my database table 2 important date columns: StartDate (Not null) and EndDate(Allowed Null).
I want to ensure that all records in the table would always create perfect contiues date ranges with no holes inside.
Wor example there may not be records [1-may..1-may, 3-may-...] because there would be a hole [2-may...2-may]. Holes are not allowed.
And overlapping is not allowed, for example [1-may..1-may, 1-may-2may, 3-may-...] is not allowed because overlapping occures on day 1-may. Overlapping and holes are not allowed. But it is allowed that table has no records at all. But all DML manipulations with existing records must ensure that overlapping and holes won't occur.
How to write such check? How to ensure that data ranges would stay continous with no holes and no overlaps?
Oracle 11g.You're setting the wrong value for the start of a group when there is no (null) lagging end date. In my example I set the value to 0 when it was null as I was expecting each group to start at 1. In your case you've set the date to 1/1/1900 which isn't necessarily the day before the first start date of the group. Instead just default it to the start date - 1 to force a match...
SQL> ed
Wrote file afiedt.buf
1 with t as (select 1 as id, to_date('01.04.2013', 'DD.MM.YYYY') as val1, to_date('04.04.2013', 'DD.MM.YYYY') as val2 from dual union all
2 select 1, to_date('05.04.2013', 'DD.MM.YYYY'), to_date('06.04.2013', 'DD.MM.YYYY') from dual union all
3 select 1, to_date('07.04.2013', 'DD.MM.YYYY'), null from dual union all
4 select 2, to_date('01.04.2013', 'DD.MM.YYYY'), to_date('03.04.2013', 'DD.MM.YYYY') from dual union all
5 select 2, to_date('04.04.2013', 'DD.MM.YYYY'), to_date('07.04.2013', 'DD.MM.YYYY') from dual union all
6 select 2, to_date('09.04.2013', 'DD.MM.YYYY'), to_date('12.04.2013', 'DD.MM.YYYY') from dual union all
7 select 2, to_date('13.04.2013', 'DD.MM.YYYY'), null from dual union all
8 select 3, to_date('01.04.2013', 'DD.MM.YYYY'),to_date('03.04.2013', 'DD.MM.YYYY') from dual union all
9 select 3, to_date('04.04.2013', 'DD.MM.YYYY'), null from dual union all
10 select 4, to_date('01.04.2013', 'DD.MM.YYYY'), to_date('01.04.2013', 'DD.MM.YYYY') from dual union all
11 select 4, to_date('01.04.2013', 'DD.MM.YYYY'), null from dual
12 )
13 --
14 select id
15 ,val1 as "start"
16 ,val2 as "end"
17 ,lag(val2) over (partition by id order by val1)
18 ,case when
19 nvl(lag(val2) over (partition by id order by val1),val1-1) != val1-1 then
20 'hole or overlap'
21 else null
22 end as chk
23 from t
24* order by 1, 2
25 /
ID start end LAG(VAL2)OVER(PARTIT CHK
1 01-APR-2013 00:00:00 04-APR-2013 00:00:00
1 05-APR-2013 00:00:00 06-APR-2013 00:00:00 04-APR-2013 00:00:00
1 07-APR-2013 00:00:00 06-APR-2013 00:00:00
2 01-APR-2013 00:00:00 03-APR-2013 00:00:00
2 04-APR-2013 00:00:00 07-APR-2013 00:00:00 03-APR-2013 00:00:00
2 09-APR-2013 00:00:00 12-APR-2013 00:00:00 07-APR-2013 00:00:00 hole or overlap
2 13-APR-2013 00:00:00 12-APR-2013 00:00:00
3 01-APR-2013 00:00:00 03-APR-2013 00:00:00
3 04-APR-2013 00:00:00 03-APR-2013 00:00:00
4 01-APR-2013 00:00:00 01-APR-2013 00:00:00
4 01-APR-2013 00:00:00 01-APR-2013 00:00:00 hole or overlap
11 rows selected. -
Hi,
How do I group by to have a date range count and it will sum up the letter1 that is obtained from that one month.Currently i knwo how to run it daily but summarizing by one month of teh postcodes, i am not too sure.
This is table counters.
Date Postcode Letter1 Letter2
31/05/2009 810 MOM MOM
1/01/2009 810 MOM MOM
1/02/2009 810 MOM MOM
29/05/2009 812 DAD DAD
30/04/2009 832 DAD
31/05/2009 835 DAD
29/05/2009 812 MOM
29/05/2009 812 MOM MOM
DDL
create table counters
(DATETIME date,
Postcode number,
letter1 varchar2(5),
letter 2 varchar2(5));
Query I have tried:
<pre>
SELECT TO_CHAR(DATETIME, 'DD/MM/YY'),POSTCODE,
count(letter1) as letter1_TOTAL,
count(letter2) as letter2_TOTAL,
sum(case when letter1 ='MOM' then 1 else 0 end) as "MOM",
sum(case when letter2 ='DAD' then 1 else 0 end) as "DATE"
FROM counters
WHERE DATETIME >= (sysdate -180)
GROUP BY TO_CHAR(DATETIME, 'DD/MM/YY'),POSTCODE
ORDER BY TO_CHAR (DATETIME,'DD/MM/YY') DESC;
</pre>
Not sure how to do this month based.
Liek my expected results should be
Date Postcode letter1 letter2
1/01/2009 -1/02/2009 810 2 null --------->MOM occured twice in that month
1/03/2009 -1/04/2009 810 null null
1/05/2009 -1/06/2009 810 1 null
1/01/2009 -1/02/2009 812 null null
1/03/2009 -1/04/2009 812 null null
1/05/2009 -1/06/2009 812 1 1
At that one month how many times MOM/DAD has summed up in that postcode.
Edited by: CrackerJack on Jun 3, 2009 10:30 PMStill not very clear about our requirement.
SQL> WITH counters AS
2 (SELECT TO_DATE ('31/05/2009', 'DD/MM/YYYY') datetime, 810 postco
3 'MOM' letter1, 'MOM' letter2
4 FROM DUAL
5 UNION ALL
6 SELECT TO_DATE ('1/01/2009', 'DD/MM/YYYY'), 810, 'MOM', 'MOM'
7 FROM DUAL
8 UNION ALL
9 SELECT TO_DATE ('1/02/2009', 'DD/MM/YYYY'), 810, 'MOM', 'MOM'
10 FROM DUAL
11 UNION ALL
12 SELECT TO_DATE ('29/05/2009', 'DD/MM/YYYY'), 812, 'DAD', 'DAD'
13 FROM DUAL
14 UNION ALL
15 SELECT TO_DATE ('30/04/2009', 'DD/MM/YYYY'), 832, 'DAD', NULL
16 FROM DUAL
17 UNION ALL
18 SELECT TO_DATE ('31/05/2009', 'DD/MM/YYYY'), 835, 'DAD', NULL
19 FROM DUAL
20 UNION ALL
21 SELECT TO_DATE ('29/05/2009', 'DD/MM/YYYY'), 812, 'MOM', NULL
22 FROM DUAL
23 UNION ALL
24 SELECT TO_DATE ('29/05/2009', 'DD/MM/YYYY'), 812, 'MOM', 'MOM'
25 FROM DUAL)
26 SELECT * FROM COUNTERS
27 ORDER BY datetime
28 /
DATETIME POSTCODE LET LET
01-JAN-09 810 MOM MOM
01-FEB-09 810 MOM MOM
30-APR-09 832 DAD
29-MAY-09 812 MOM MOM
29-MAY-09 812 DAD DAD
29-MAY-09 812 MOM
31-MAY-09 835 DAD
31-MAY-09 810 MOM MOM
8 rows selected.I changed your group by clause to include the date range. However if you want month wise you should understand that 01-Jan-2009 to 31-Jan 2009 is considered as one month. So the date range for one month you specified in your expected result was wrong. (01-Jan-2009 to 01-Feb-2009) .
Hope the following code helps:
SQL> WITH counters AS
2 (SELECT TO_DATE ('31/05/2009', 'DD/MM/YYYY') datetime, 810 postco
3 'MOM' letter1, 'MOM' letter2
4 FROM DUAL
5 UNION ALL
6 SELECT TO_DATE ('1/01/2009', 'DD/MM/YYYY'), 810, 'MOM', 'MOM'
7 FROM DUAL
8 UNION ALL
9 SELECT TO_DATE ('1/02/2009', 'DD/MM/YYYY'), 810, 'MOM', 'MOM'
10 FROM DUAL
11 UNION ALL
12 SELECT TO_DATE ('29/05/2009', 'DD/MM/YYYY'), 812, 'DAD', 'DAD'
13 FROM DUAL
14 UNION ALL
15 SELECT TO_DATE ('30/04/2009', 'DD/MM/YYYY'), 832, 'DAD', NULL
16 FROM DUAL
17 UNION ALL
18 SELECT TO_DATE ('31/05/2009', 'DD/MM/YYYY'), 835, 'DAD', NULL
19 FROM DUAL
20 UNION ALL
21 SELECT TO_DATE ('29/05/2009', 'DD/MM/YYYY'), 812, 'MOM', NULL
22 FROM DUAL
23 UNION ALL
24 SELECT TO_DATE ('29/05/2009', 'DD/MM/YYYY'), 812, 'MOM', 'MOM'
25 FROM DUAL)
26 SELECT TO_CHAR (TRUNC (datetime, 'MONTH'), 'DD/MM/YYYY')
27 || '-'
28 || TO_CHAR (LAST_DAY (datetime), 'DD/MM/YYYY') date_range,
29 postcode, COUNT (letter1) AS letter1_total,
30 COUNT (letter2) AS letter2_total,
31 SUM (CASE
32 WHEN letter1 = 'MOM'
33 THEN 1
34 ELSE 0
35 END) AS "MOM", SUM (CASE
36 WHEN letter2 = 'DAD'
37 THEN 1
38 ELSE 0
39 END) AS "DAD"
40 FROM counters
41 WHERE datetime >= (SYSDATE - 180)
42 GROUP BY TO_CHAR (TRUNC (datetime, 'MONTH'), 'DD/MM/YYYY')
43 || '-'
44 || TO_CHAR (LAST_DAY (datetime), 'DD/MM/YYYY'),
45 postcode
46 ORDER BY TO_CHAR (TRUNC (datetime, 'MONTH'), 'DD/MM/YYYY')
47 || '-'
48 || TO_CHAR (LAST_DAY (datetime), 'DD/MM/YYYY')
49 /
DATE_RANGE POSTCODE LETTER1_TOTAL LETTER2_TOTAL MOM DAD
01/01/2009-31/01/2009 810 1 1 1 0
01/02/2009-28/02/2009 810 1 1 1 0
01/04/2009-30/04/2009 832 1 0 0 0
01/05/2009-31/05/2009 810 1 1 1 0
01/05/2009-31/05/2009 812 3 2 2 1
01/05/2009-31/05/2009 835 1 0 0 0
6 rows selected.Regards,
Jo
Edit: Added code tags -
Hi Experts,
I have created a linked server to connect to mysql DB . The query is executing fine currently filter is based on the on going month.
The query actually fetches the records from 2 tables User and time sheet to find how many hours the users have .
Now we check the Hours for a period of 10th of the current month and 10th of the upcoming month .
So for now date range will be between 2014/10/05 and 2014/10/06. This logic i have implemented in the query .
Based on the query a report is generated which is sent out every Wednesday .Now suppose its 5th of June 2014 .
The query will fail because the date range is derived based upon
where cast(t.created_on as Date) > Concat(year(now()),"-",month(now()),"-","10")
AND cast(t.created_on as Date) <=Concat(year(now()),"-",month(now())+1,"-","10")
Please provide with a date filter like the report runs anytime the data is not affected. Like if the report is run in the
first week of a new month date range should be previous month Date 10 and current month Date 10 and if the report is run after 10th of the current month then the date range should be between 10th of current month and 10 of upcoming month . Kindly
help
Select * From
OPENQUERY
(Mysql,
'Select
Sum(t.hours),
Concat(u.firstname," ",
u.lastname) as Name
From mysql.time_entries t
Inner Join
users u
on u.id = t.user_id
where cast(t.created_on as Date) >
Concat(year(now()),"-",month(now()),"-","10")
AND
cast(t.created_on as Date) <=Concat(year(now()),"-",month(now())+1,"-","10")
Group By u.firstname,u.lastname
Union all
Select Sum(0) as hours,
Concat(firstname," ",
lastname) as Name
from users
where id not in(
Select
t.user_id
From mysql.time_entries t
Inner Join
users u
on u.id = t.user_id
where cast(t.created_on as Date) >
Concat(year(now()),"-",month(now()),"-","10")
AND
cast(t.created_on as Date) <=Concat(year(now()),"-",month(now())+1,"-","10"))
And firstname not in( "xyz")
GRoup by firstName,lastname'
goI recommend use CLOSED-OPEN dates rather than OPEN-CLOSED dates...
Hopefully this helps with your logic:
DECLARE @ReportDate TABLE
[ReportDate] DATE,
[mDay] AS DAY([ReportDate]),
[Beg] AS DATEADD(month, CASE WHEN DAY([ReportDate]) < 10 THEN -1 ELSE 0 END, [ReportDate]),
[End] AS DATEADD(month, CASE WHEN DAY([ReportDate]) < 10 THEN 0 ELSE 1 END, [ReportDate]),
[ReportBeg] AS DATEADD(month, CASE WHEN DAY([ReportDate]) < 10 THEN -1 ELSE 0 END, DATEADD(day, 10 - DAY([ReportDate]), [ReportDate])),
[ReportEnd] AS DATEADD(month, CASE WHEN DAY([ReportDate]) < 10 THEN 0 ELSE 1 END, DATEADD(day, 10 - DAY([ReportDate]) + 1, [ReportDate]))
INSERT INTO @ReportDate(ReportDate)
VALUES
('7-May-2014'),
('10-May-2014'),
('15-May-2014');
SELECT
CASE WHEN SYSDATETIME() >= [ReportBeg] AND SYSDATETIME() < [ReportEnd] THEN 1 ELSE 0 END
FROM @ReportDate; -
Assign Month within a date range (by most days in a given month)
I have a begin and end date, sample data as such
select to_date('01-13-12','mm-dd-yy') from_dt,
to_date('02-23-12','mm-dd-yy') to_dt
from dual
union all
select to_date('03-15-2012','mm-dd-yy') from_dt,
to_date('04-16-2012','mm-dd-yy') to_dt
from dual
union all
select to_date('05-13-2012','mm-dd-yy') from_dt,
to_date('07-23-2012','mm-dd-yy') to_dt
from dual
How do I assign a month by the most days in a month within that date range? Sometimes the date range might have the exact same amount of days in a month (like 3/15/2012 has 16 days and 4/16/2012 has 16 days). In this case, I want the earlier month (march).
So from the sample data:
01/13/2012, 02/23/2012, February
03/15/2012, 04/16/2012, March
05/13/2012, 07/23/2012, June
Thanks
Edited by: user4422426 on Mar 1, 2012 5:15 PMHi,
Here's one way:
WITH cntr AS
SELECT LEVEL - 1 AS n
FROM (
SELECT 1 + MAX (to_dt - from_dt) AS max_day_cnt
FROM table_x
CONNECT BY LEVEL <= max_day_cnt
, got_r_num AS
SELECT x.from_dt, x.to_dt
, TRUNC (x.from_dt + c.n, 'MONTH') AS month
, count (*) AS cnt
, ROW_NUMBER () OVER ( PARTITION BY from_dt, to_dt
ORDER BY COUNT (*) DESC
, TRUNC (x.from_dt + c.n, 'MONTH')
) AS r_num
FROM cntr c
JOIN table_x x ON c.n <= x.to_dt - x.from_dt
GROUP BY x.from_dt, x.to_dt
, TRUNC (x.from_dt + c.n, 'MONTH')
SELECT from_dt, to_dt
, TO_CHAR (month, 'Mon YYYY') AS mon
, cnt
FROM got_r_num
WHERE r_num = 1
;Thanks for posting code to create the same data. Please test your code before you post it: you got the order of arguments to TO_DATE reversed. -
Extracting a count of distinct values between two date ranges over months
Hi All,
I am having a bit of difficulty in figuring out the query to build a list of active campaigns over a date range.
i.e. I have a table with campaign IDs and their start and end date details like this
Campaign_id Start_date End_date
10001 1-Jun-09 31-May-11
10002 1-Jun-09 23-Jun-11
30041 21-Aug-09 31-Dec-09
20005 3-Jun-10 31-May-11
90021 21-Nov-09 30-Nov-10
54000 1-Jun-11 1-Dec-12
35600 1-Mar-10 31-Mar-12 What the above data means is, for eg. the campaign 10001 is active from 1-Jun-09 to 31-May-11 i.e. for 24 months (inclusive of the month Jun-09 and May-11)
What I need to figure out is the counts of active campaigns between a date range and display that active count at a month level (for e.g. lets say we want to see all the campaigns that were active
between the date range '01-JUN-2007' and '30-APR-2012' ). So the partial output would be as seen below. The list would continue till december-2012
Month Year Count of active campaigns
Jan 2009 0
Feb 2009 0
Mar 2009 0
Apr 2009 0
May 2009 0
Jun 2009 2
Jul 2009 2
Aug 2009 3
Sep 2009 3
Oct 2009 3
Nov 2009 4
Dec 2009 4
Jan 2010 3
Feb 2010 3
Mar 2010 4
Apr 2010 4
Dec 2012 1 Could anybody please help me with the right query for this.
Thanks a lot for help
Regards
Goldiset pagesize 40
with tab as
select 1 id, sysdate -100 start_date, sysdate end_date from dual
union
select 1 id, sysdate -200 start_date, sysdate -150 end_date from dual
union
select 1 id, sysdate -600 start_date, sysdate - 400 end_date from dual
union
select 1 id, sysdate -300 start_date, sysdate - 150 end_date from dual
union
select 2 id, sysdate -100 start_date, sysdate-50 end_date from dual
year_tab as
select
add_months(min_date, level -1) m
from
select min(trunc(start_date,'YYYY')) min_date, add_months(max(trunc(end_date,'YYYY')), 12) max_date
from tab
connect by level <= months_between(max_date, min_date)
select to_char(m,'YYYY') year_,
to_char(m,'Month') month_,
nvl(act, 0) act
from year_tab,
select m date_,count(*) act
from tab, year_tab
where m between trunc(start_date,'MM') and trunc(end_date,'MM')
group by m
) month_tab
where m = date_(+)
order by m;
YEAR_ MONTH_ ACT
2010 January 0
2010 February 0
2010 March 0
2010 April 0
2010 May 0
2010 June 0
2010 July 0
2010 August 0
2010 September 1
2010 October 1
2010 November 1
2010 December 1
2011 January 1
2011 February 1
2011 March 1
2011 April 0
2011 May 0
2011 June 0
2011 July 1
2011 August 1
2011 September 1
2011 October 2
2011 November 2
2011 December 2
2012 January 2
2012 February 2
2012 March 2
2012 April 1
2012 May 1
2012 June 0
2012 July 0
2012 August 0
2012 September 0
2012 October 0
2012 November 0
2012 December 0
36 rows selected. -
All months in date range plus running count
Oracle 11g
Hello all,
Having trouble getting the following query to return proper results. Have a table with a MEMBERNO, BUSINESS_LINE, ELIGIBILITY_START_DATE, ELIGIBILITY_END_DATE.
MEMBERNO is not unique
BUSINESS_LINE is not either
Start and end date are periods of time where: MEMBERNO&BUSINESS_LINE have changed
I need to list the member number, business_line, and each month that falls within the date range beginning with eligibility_start_date & eligibility_end_date, as well as a running count of the total in that span.
Eg.
member, business_line, month, year, count
1234, bus1, 01, 2001, 1
1234, bus1, 02, 2001, 2
1234, bus1, 03, 2001, 3
Here is my SQL, it is not sequencing the months dates correctly and I can not figure out why. Any help is very appreciated:
SELECT memberno,
business_line,
TO_CHAR (ADD_MONTHS (start_date, LEVEL - 1), 'MM') as MONTH,
TO_CHAR (ADD_MONTHS (start_date, LEVEL - 1), 'YYYY') as YEAR,
ROW_NUMBER () OVER (PARTITION BY key1 ORDER BY start_date ASC) as MEMBER_MONTH_COUNT
FROM (SELECT memberno,
business_line,
eligibility_start_date as start_date,
eligibility_end_date as end_date,
member_nbr || business_line as key1
FROM eligibility)
CONNECT BY LEVEL <=
MONTHS_BETWEEN (TRUNC (END_DATE, 'MM'),
TRUNC (START_date, 'MM'))
+ 1;
Edited by: 935047 on Jul 25, 2012 5:58 AM
Edited by: 935047 on Jul 25, 2012 6:18 AM935047 wrote:
I need to list the member number, business_line, and each month that falls within the date range beginning with eligibility_start_date & eligibility_end_date, as well as a running count of the total in that span.
Eg.
member, business_line, month, year, count
1234, bus1, 01, 2001, 1
1234, bus1, 02, 2001, 2
1234, bus1, 03, 2001, 3I could not understand what the Running Count mean. Hence, I used Row_Number (Same as you did).
Below query might match yours.
with data (memb_no, bus_line, st_date, end_date) as
select 1234, 'bus1', to_date('01-01-2001', 'MM-DD-YYYY'), to_date('06-30-2001', 'MM-DD-YYYY') from dual
union all
select 1234, 'bus1', to_date('07-01-2001', 'MM-DD-YYYY'), to_date('07-30-2002', 'MM-DD-YYYY') from dual
min_max as
select memb_no, bus_line, min(st_date) st_date, max(end_date) end_date
from data
group by memb_no, bus_line
lvl as
select level l
from dual
connect by level <= (select max(round(months_between(end_date, st_date))) from min_max)
select memb_no,
bus_line,
to_char(add_months(st_date, l - 1), 'MM') months,
to_char(add_months(st_date, l - 1), 'YYYY') Year,
row_number() over (partition by memb_no, bus_line order by st_date) cnt
from min_max cross join lvl
order by year, months;
----OUTPUT------------------------
MEMB_NO BUS_LINE MONTHS YEAR CNT
1234 bus1 01 2001 1
1234 bus1 02 2001 19
1234 bus1 03 2001 3
1234 bus1 04 2001 4
1234 bus1 05 2001 5
1234 bus1 06 2001 6
1234 bus1 07 2001 7
1234 bus1 08 2001 8
1234 bus1 09 2001 9
1234 bus1 10 2001 10
1234 bus1 11 2001 11
1234 bus1 12 2001 12
1234 bus1 01 2002 13
1234 bus1 02 2002 14
1234 bus1 03 2002 15
1234 bus1 04 2002 16
1234 bus1 05 2002 17
1234 bus1 06 2002 18
1234 bus1 07 2002 2
19 rows selected -
Hi ,
I have a column with date range in the format 07/21/2014-07/21/2014,
07/16/2014-07/16/2014
07/22/2014-07/22/2014
there will be thousands of records like this.
In ssrs I need to pass a pramater with date range =07/16/2014-07/22/2014 then it should display all the records between those dates. I not getting the logic here how to write it. it is pulling all the dates it is not filtering the dates right now.
Can anybody help me on this issue..
BALUSUSRIHARSHAIt will be much easier if you have two columns holding the range and you pass two parameters to find out the overlapping ranges.
select c1, ..., cn
from T
where @sdt <= dt2 and @edt >= dt1; -- considering the range (dt1, dt2)
or just the exact range:
select c1, ..., cn
from T
where dt1 = @sdt and dt2 = @edt; -- considering the range (dt1, dt2)
Since you store the range in one column of character data type then you need to split the value in two, the start and end points of the range, and do the same with the parameter but this will be easier to change the report to send two parameters instead
one.
Search in this forum or Transact-SQL forum for a function to split a string. Here is a good reference:
Arrays and Lists in SQL Server
http://www.sommarskog.se/arrays-in-sql.html
Once you have created the function, it is a matter of using the APPLY operator, pivot the range and use same predicate as in my first query.
Here is an example but I would encorage you to change the model.
SET NOCOUNT ON;
USE tempdb;
GO
--Itzik's VATN
CREATE FUNCTION dbo.GetNums(@n AS BIGINT) RETURNS TABLE
AS
RETURN
WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS n FROM L5)
SELECT TOP (@n) n FROM Nums ORDER BY n;
GO
--Erland's split_me
CREATE FUNCTION dbo.inline_split_me(@param nvarchar(MAX))
RETURNS TABLE AS
RETURN(
SELECT
ROW_NUMBER() OVER(ORDER BY n) AS rn,
LTRIM(rtrim(convert(nvarchar(4000),
substring(@param, n,
charindex(N'-' COLLATE Slovenian_BIN2,
@param + convert(nvarchar(MAX), N'-'),
n) - n)
))) AS Value
FROM dbo.GetNums(LEN(@param))
WHERE substring(convert(nvarchar(MAX), N'-') + @param, n, 1) = N'-' COLLATE Slovenian_BIN2
GO
DECLARE @r varchar(21) = '07/16/2014-07/22/2014';
DECLARE @T TABLE (dt_range varchar(21));
INSERT INTO @T (dt_range)
VALUES
('07/21/2014-07/21/2014'),
('07/16/2014-07/16/2014'),
('07/22/2014-07/22/2014'),
('07/23/2014-07/25/2014');
SELECT
T.dt_range,
R.sdt,
R.edt,
W.p_sdt,
W.p_edt
FROM
@T AS T
CROSS APPLY
SELECT
CAST([1] AS date) AS sdt,
CAST([2] AS date) AS edt
FROM
dbo.inline_split_me(T.dt_range) AS A
PIVOT
MAX(Value)
FOR rn IN ([1], [2])
) AS P
) AS R
CROSS JOIN
SELECT
CAST([1] AS date) AS p_sdt,
CAST([2] AS date) AS p_edt
FROM
dbo.inline_split_me(@r) AS A
PIVOT
MAX(Value)
FOR rn IN ([1], [2])
) AS P
) AS W
WHERE
R.sdt <= W.p_edt
AND R.edt >= W.p_sdt;
GO
DROP FUNCTION dbo.inline_split_me, dbo.GetNums;
GO
Notice that the last row inserted is not part of the result set because it falls outside of the parameter date range.
AMB
Some guidelines for posting questions... -
Group by with date range.
Hi,
I am looking for effective usage of Group by against date range.
I have a transaction table as below.
Date customer_no amount_paid
01-Dec-13 001 500
02-Dec-13 001 360
09-Dec-13 001 200
02-Nov-13 001 360
09-Nov-13 001 200
02-Nov-13 001 360
09-Oct-13 001 200
02-Oct-13 001 360
09-Oct-13 001 200
02-Sep-13 001 360
09-Sep-13 001 200
............... etc.
I would like to see sum(amount_paid) by past date ranges 1-30 days, 31-60 days, 61-90 days.
Below are expected results.
Customer Duration amount_paid
001 1-30 980
001 31-60 450
001 61-90 1200
002 1-30 300
002 31-60 490
002 61-90 320
003 1-30 450
......................etc.
I have to group by customer no and date range (1-30, 31-60, 61-90..etc).
Can someone help me getting query for this.
Thanks...
Sreeram.SQL> with t
2 as
3 (
4 select to_date('01-Dec-13', 'dd-Mon-rr') dt, '001' customer_no, 500 amount_paid from dual
5 union all
6 select to_date('02-Dec-13', 'dd-Mon-rr') dt, '001' customer_no, 360 amount_paid from dual
7 union all
8 select to_date('09-Dec-13', 'dd-Mon-rr') dt, '001' customer_no, 200 amount_paid from dual
9 union all
10 select to_date('02-Nov-13', 'dd-Mon-rr') dt, '001' customer_no, 360 amount_paid from dual
11 union all
12 select to_date('09-Nov-13', 'dd-Mon-rr') dt, '001' customer_no, 200 amount_paid from dual
13 union all
14 select to_date('02-Nov-13', 'dd-Mon-rr') dt, '001' customer_no, 360 amount_paid from dual
15 union all
16 select to_date('09-Oct-13', 'dd-Mon-rr') dt, '001' customer_no, 200 amount_paid from dual
17 union all
18 select to_date('02-Oct-13', 'dd-Mon-rr') dt, '001' customer_no, 360 amount_paid from dual
19 union all
20 select to_date('09-Oct-13', 'dd-Mon-rr') dt, '001' customer_no, 200 amount_paid from dual
21 union all
22 select to_date('02-Sep-13', 'dd-Mon-rr') dt, '001' customer_no, 360 amount_paid from dual
23 union all
24 select to_date('09-Sep-13', 'dd-Mon-rr') dt, '001' customer_no, 200 amount_paid from dual
25 )
26 select customer_no
27 , ((grp_val - 1) * 30) + 1 start_val
28 , grp_val * 30 end_val
29 , sum(amount_paid) amount_paid
30 from (
31 select dt
32 , customer_no
33 , amount_paid
34 , ceil(sum(dt_interval) over(partition by customer_no order by dt)/30) grp_val
35 from (
36 select dt
37 , customer_no
38 , amount_paid
39 , nvl(dt - lag(dt) over(partition by customer_no order by dt), 1) dt_interval
40 from t
41 )
42 )
43 group
44 by customer_no
45 , grp_val
46 order
47 by grp_val;
CUS START_VAL END_VAL AMOUNT_PAID
001 1 30 560
001 31 60 760
001 61 90 920
001 91 120 1060
SQL> -
Compute Date Range with SQL Statement
I'm sure there is a way to do this in SQL, but I cannot figure it out. I can write a PL/SQL script to do it, but would prefer using a SQL Statement. My database is Oracle Database 10.2.0.4.0.
I have a table that contains information such as the employee number, department id, and the effective date of when the person started in that department. There is data in another table that I want to update their department number in based on their effective date range. If I could figure out how to select the effective date range correctly, I can do the rest.
I have data such as:
EMP_ID DEPT_NO EFFECTIVE
101 1000 1/15/2001
101 1050 5/24/2005
101 2010 6/8/2008
101 1000 8/2/2010
I want to write a SELECT statement that returns something like this where the END_DATE is the day before the EFFECTIVE date and the last record does not have an END_DATE because they are still assigned to that department. Also, the first record in the column, I don't want to select a DEPT_NO because the effective date logic was added in January 2001 so if a person started back in 1985 they could have switched departments zero to many times so I'm not going to update any data for that period:
EMP_ID DEPT_NO EFFECTIVE END_DATE
101 1/14/2001
101 1000 1/15/2001 5/23/2005
101 1050 5/24/2005 6/7/2008
101 2010 6/8/2008 8/1/2010
101 1000 8/2/2010
Below is a script to create the data in a temp table that can be used to write a SELECT statement on. I have added two employee records with different dates.
create table temp_activity
(emp_id number(12),
dept_no number(12),
effective date);
INSERT INTO temp_activity
(EMP_ID,DEPT_NO,EFFECTIVE)
VALUES
(101,1000,to_date('1/15/2001','MM/DD/YYYY'))
INSERT INTO temp_activity
(EMP_ID,DEPT_NO,EFFECTIVE)
VALUES
(101,1050,to_date('5/24/2005','MM/DD/YYYY'))
INSERT INTO temp_activity
(EMP_ID,DEPT_NO,EFFECTIVE)
VALUES
(101,2010,to_date('6/8/2008','MM/DD/YYYY'))
INSERT INTO temp_activity
(EMP_ID,DEPT_NO,EFFECTIVE)
VALUES
(101,1000,to_date('8/2/2010','MM/DD/YYYY'))
INSERT INTO temp_activity
(EMP_ID,DEPT_NO,EFFECTIVE)
VALUES
(102,1040,to_date('1/15/2001','MM/DD/YYYY'))
INSERT INTO temp_activity
(EMP_ID,DEPT_NO,EFFECTIVE)
VALUES
(102,2000,to_date('6/16/2006','MM/DD/YYYY'))
Any help is appreciated. This is probably easy, but I cannot get my brain wrapped around it.
Thanks - mikeselect emp_id,
dept_no,
effective,
end_date
from (
select emp_id,
dept_no,
effective,
lead(effective) over(partition by emp_id order by effective) - 1 end_date,
row_number() over(partition by emp_id order by effective) rn
from temp_activity
union all
select emp_id,
null dept_no,
null effective,
min(effective) - 1 end_date,
0 rn
from temp_activity
group by emp_id
order by emp_id,
rn
EMP_ID DEPT_NO EFFECTIVE END_DATE
101 01/14/2001
101 1000 01/15/2001 05/23/2005
101 1050 05/24/2005 06/07/2008
101 2010 06/08/2008 08/01/2010
101 1000 08/02/2010
102 01/14/2001
102 1040 01/15/2001 06/15/2006
102 2000 06/16/2006
8 rows selected.
SQL> SY. -
Select Row immediately previous and following a date range
I have a query which returns two values within a given date range (colA, colB). This works great. However, I also need to return (in a separate query) the entries immediately previous and following this current date range (same two values).
I am more familiar with MySQL where the query would include an "Order by date desc limit 1" for the row previous to the original query or "Order by date asc limit 1" for the row following the original query.
What is the best way to return these rows within Oracle?Hi,
This is an example of a Top-N Query, where you want to pick N items (N=1 in this case) from the top of an ordered list.
This problem is a little trickier, because you want to pick from two lists, the rows before the specieifed date range (in descending order) and the rows after the range.
The easiest way might be a UNION of two separate queries, using WHERE ROWNUM = 1 in each one.
The solution below is easier to generalize, e.g. if you want the first and last row from each department.
WITH
e AS
SELECT empno, ename, hiredate
, ROW_NUMBER () OVER
( ORDER BY CASE
WHEN hiredate < TO_DATE ( '01-JAN-1982'
, 'DD-MON-YYYY'
) -- Start of date range
THEN hiredate
END
DESC NULLS LAST
) AS pre_num
, ROW_NUMBER () OVER
( ORDER BY CASE
WHEN hiredate > TO_DATE ( '31-DEC-1982'
, 'DD-MON-YYYY'
) -- End of date range
THEN hiredate
END
) AS post_num
FROM scott.emp
SELECT empno, ename, hiredate
FROM e
WHERE pre_num = 1
OR post_num = 1
;Results (last hire before 1982 and first hire after 1982):
EMPNO ENAME HIREDATE
7788 SCOTT 19-APR-87
7900 JAMES 03-DEC-81 -
SUM(Case how to use this structure to get average values over date range
I am using:
Oracle SQL Developer (3.0.04) Build MAin-04.34 Oracle Database 11g Enterprise Edition 11.2.0.1.0 - 64bit Production
How do I use the sum function with a case structure inside.
so I have data that looks like has an ID, date, and value. I am looking to get the 7 day average for the date range of 4/1/2013 thru 4/20/2013
with t as (
select 1 ID_Key,to_date('4/1/2013','mm-dd-yyyy') date_val, 10 Value_num from dual union all
select 1 ID_key,to_date('4/2/2013','mm-dd-yyyy'), 15 from dual union all
select 1 ID_key,to_date('4/3/2013','mm-dd-yyyy'), 20 from dual union all
select 1 ID_key,to_date('4/5/2013','mm-dd-yyyy'), 0 from dual union all
select 1 ID_key,to_date('4/8/2013','mm-dd-yyyy'), 12 from dual union all
select 1 ID_key,to_date('4/9/2013','mm-dd-yyyy'), 8 from dual union all
select 1 ID_key,to_date('4/10/2013','mm-dd-yyyy'), 6 from dual union all
select 1 ID_key,to_date('4/12/2013','mm-dd-yyyy'), 10 from dual union all
select 1 ID_key,to_date('4/13/2013','mm-dd-yyyy'), 0 from dual union all
select 1 ID_key,to_date('4/14/2013','mm-dd-yyyy'), 0 from dual union all
select 1 ID_key,to_date('4/15/2013','mm-dd-yyyy'), 10 from dual union all
select 1 ID_key,to_date('4/16/2013','mm-dd-yyyy'), 5 from dual union all
select 1 ID_key,to_date('4/17/2013','mm-dd-yyyy'), 2 from dual union all
select 1 ID_key,to_date('4/20/2013','mm-dd-yyyy'), 3 from dual union all
select 2 ID_key,to_date('4/3/2013','mm-dd-yyyy'), 12 from dual union all
select 2 ID_key,to_date('4/5/2013','mm-dd-yyyy'), 15 from dual union all
select 2 ID_key,to_date('4/6/2013','mm-dd-yyyy'), 5 from dual union all
select 2 ID_key,to_date('4/7/2013','mm-dd-yyyy'), 7 from dual union all
select 2 ID_key,to_date('4/9/2013','mm-dd-yyyy'), 10 from dual union all
select 2 ID_key,to_date('4/11/2013','mm-dd-yyyy'), 5 from dual union all
select 2 ID_key,to_date('4/12/2013','mm-dd-yyyy'), 0 from dual union all
select 2 ID_key,to_date('4/13/2013','mm-dd-yyyy'), 0 from dual union all
select 2 ID_key,to_date('4/15/2013','mm-dd-yyyy'), 6 from dual union all
select 2 ID_key,to_date('4/16/2013','mm-dd-yyyy'), 8 from dual union all
select 2 ID_key,to_date('4/17/2013','mm-dd-yyyy'), 0 from dual union all
select 2 ID_key,to_date('4/18/2013','mm-dd-yyyy'), 10 from dual union all
select 2 ID_key,to_date('4/19/2013','mm-dd-yyyy'), 5 from dual
)**Please let me know if the table does not load.
I would like to get the 7 day average as long as there is date for that row has enough previous dates, it not then it will return null.
the results should look like this
ID_Key date_val Value_num 7Day_Avg 7Day_Avg2
1 4/1/2013 10 null null
1 4/2/2013 15 null null
1 4/3/2013 20 null null
1 4/5/2013 0 null null
1 4/8/2013 12 6.71 11.75
1 4/9/2013 8 5.71 10.00
1 4/10/2013 6 3.71 6.50
1 4/12/2013 10 5.14 9.00
1 4/13/2013 0 5.14 7.20
1 4/14/2013 0 5.14 6.00
1 4/15/2013 10 4.86 5.67
1 4/16/2013 5 4.42 5.17
1 4/17/2013 2 3.85 4.50
1 4/20/2013 3 2.86 4.00
2 4/3/2013 12 null null
2 4/5/2013 15 null null
2 4/6/2013 5 null null
2 4/7/2013 7 5.57 9.75
2 4/9/2013 10 7.00 9.80
2 4/11/2013 5 6.00 8.40
2 4/12/2013 0 3.86 5.40
2 4/13/2013 0 3.14 4.40
2 4/15/2013 6 3.00 4.20
2 4/16/2013 8 2.71 3.80
2 4/17/2013 0 2.71 3.17
2 4/18/2013 10 3.43 4.00
2 4/19/2013 5 4.14 4.83As you may notice, there are gaps in the dates, so the value are then treated as zeros for the 7Day_Avg and then ignored for teh 7Day_Avg2 (not counted as number of days averaged do to no valu_num row)
I was trying something like this to start, but getting error "missing keyword"
select
t.*/,
sum(
case
when date_val between :day2 - 6 and :day2
then value_num between date_val - 6 and date_val
else null
end
as 7Day_avg
form tShould I have the case structure outside the sum function?
Any thoughts??
Edited by: 1004407 on Jun 7, 2013 11:06 AMHi,
If you want the average of the last 7 days, including the current day, then then RANGE should be 6 PRECEDING, not 7.
Try this:
WITH got_min_date_val AS
SELECT id_key, date_val, value_num
, MIN (date_val) OVER () AS min_date_val
FROM t
WHERE date_val BETWEEN TO_DATE ('04-01-2013', 'mm-dd-yyyy')
AND TO_DATE ('04-20-2013', 'mm-dd-yyyy')
SELECT id_key, date_val, value_num
, CASE
WHEN date_val >= min_date_val + 6
THEN SUM (value_num) OVER ( PARTITION BY id_key
ORDER BY date_val
RANGE 6 PRECEDING
/ 7
END AS avg_7_day
, CASE
WHEN date_val >= min_date_val + 6
THEN AVG (value_num) OVER ( PARTITION BY id_key
ORDER BY date_val
RANGE 6 PRECEDING
END AS avg_7_day_2
FROM got_min_date_val
ORDER BY id_key
, date_val
Output:
ID_KEY DATE_VAL VALUE_NUM AVG_7_DAY AVG_7_DAY_2
1 01-APR-13 10
1 02-APR-13 15
1 03-APR-13 20
1 05-APR-13 0
1 08-APR-13 12 6.71 11.75
1 09-APR-13 8 5.71 10.00
1 10-APR-13 6 3.71 6.50
1 12-APR-13 10 5.14 9.00
1 13-APR-13 0 5.14 7.20
1 14-APR-13 0 5.14 6.00
1 15-APR-13 10 4.86 5.67
1 16-APR-13 5 4.43 5.17
1 17-APR-13 2 3.86 4.50
1 20-APR-13 3 2.86 4.00
2 03-APR-13 12
2 05-APR-13 15
2 06-APR-13 5
2 07-APR-13 7 5.57 9.75
2 09-APR-13 10 7.00 9.80
2 11-APR-13 5 6.00 8.40
2 12-APR-13 0 3.86 5.40
2 13-APR-13 0 3.14 4.40
2 15-APR-13 6 3.00 4.20
2 16-APR-13 8 2.71 3.80
2 17-APR-13 0 2.71 3.17
2 18-APR-13 10 3.43 4.00
2 19-APR-13 5 4.14 4.83
Message was edited by: FrankKulash
Sorry; I meant to reply to OP, not to Greg
Maybe you are looking for
-
I've put 2003 64bit on an old ide drive. Used the workstation set up guide from another thread-- video accelerated, dx9b in place. Audio works, lan works (thx for the driver links) -- picked up satellite internet through ICS on another machine (W2K
-
Hi! I create fillable forms on my Mac using Adobe Acrobat and both PC and Mac customers fill in the forms and submit them to their own customers. When I fill in the form on my Mac (using Adobe Acrobat) and email it to me and open the PDF on my Androi
-
I am new to Pages. I am trying to produce a newsletter and I am having trouble with the layout and column parts. I tried to vary the column width and followed the directions in the pdf manual. But it isn't working for me. I probably need a step by st
-
My itunes won't burn playlist -i get 'an unknown error occurred' -why?
my itunes won't burn my playlists -i get 'an unknown error occurred' -why? i just upgrtaded from an 80 to 160 GB, btw... help!!! thanks!
-
Actually I asked a version of this question several days ago. The following sites do not emerge most of the time. Or if they do, they take about 15 minutes to download!: '''http://movies.nytimes.com''' http://www.washingtonpost.com/gog/movies/ The ab