SUBTOTALS of a GROUP BY IN ORACLE











up vote
1
down vote

favorite












This is the table I have.




TASK_CD | STATUS | DUE_DATE
----------------------------------
T0001 | NW | SYSDATE + 1
T0001 | IP | SYSDATE
T0001 | AG | SYSDATE
T0002 | NW | SYSDATE - 1
T0002 | NW | SYSDATE - 2
T0003 | AG | SYSDATE + 1


This is the query I have right now



select TASK_CD, STATUS, SUM(1) TOTALS, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) FUTURE,
SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) TODAY,
SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) OVERDUE,
FROM TM_TASK GROUP BY TASK_CD, STATUS;


result will be




TASK_CD | STATUS | TOTALS | FUTURE | TODAY | OVERDUE
----------------------------------------------------
T0001 | NW | 1 | 1 | 0 | 0
T0001 | IP | 1 | 0 | 1 | 0
T0001 | AG | 1 | 0 | 1 | 0
T0002 | NW | 2 | 0 | 0 | 2
T0003 | AG | 1 | 1 | 0 | 0


By removing STATUS from select and group, I get




TASK_CD | TOTALS | FUTURE | TODAY | OVERDUE
-----------------------------------------------
T0001 | 3 | 1 | 2 | 0
T0002 | 2 | 0 | 0 | 2
T0003 | 1 | 1 | 0 | 0


Is there a way to combine both and combine the results, giving me TOTALS_ALL, FUTURE_TOTALS, OVERDUE_TOTALS, TODAY_TOTALS where these are the sums when status is not considered for the GROUP BY




TASK_CD | STATUS | TOTALS | FUTURE | TODAY | OVERDUE| TOTALS_ALL | FUTURE_TOTAL | TODAY_TOTAL | OVERDUE_TOTAL
T0001 | NW | 1 | 1 | 0 | 0 | 3 | 1
| 2 | 0
T0001 | IP | 1 | 0 | 1 | 0 | 3 | 1
| 2 | 0
T0001 | AG | 1 | 0 | 1 | 0 | 3 | 1
| 2 | 0
T0002 | NW | 2 | 0 | 0 | 2 | 2 | 0
| 0 | 2
T0003 | AG | 1 | 1 | 0 | 0 | 1 | 1
| 0 | 0









share|improve this question
























  • Although it will not give you the same structure, as you've shown you expect, you could consider using ROLLUP (or for more complex cases CUBE) clause for GROUP BY - it is designed to calculate totals and sub-totals.
    – Hilarion
    Nov 19 at 23:26















up vote
1
down vote

favorite












This is the table I have.




TASK_CD | STATUS | DUE_DATE
----------------------------------
T0001 | NW | SYSDATE + 1
T0001 | IP | SYSDATE
T0001 | AG | SYSDATE
T0002 | NW | SYSDATE - 1
T0002 | NW | SYSDATE - 2
T0003 | AG | SYSDATE + 1


This is the query I have right now



select TASK_CD, STATUS, SUM(1) TOTALS, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) FUTURE,
SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) TODAY,
SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) OVERDUE,
FROM TM_TASK GROUP BY TASK_CD, STATUS;


result will be




TASK_CD | STATUS | TOTALS | FUTURE | TODAY | OVERDUE
----------------------------------------------------
T0001 | NW | 1 | 1 | 0 | 0
T0001 | IP | 1 | 0 | 1 | 0
T0001 | AG | 1 | 0 | 1 | 0
T0002 | NW | 2 | 0 | 0 | 2
T0003 | AG | 1 | 1 | 0 | 0


By removing STATUS from select and group, I get




TASK_CD | TOTALS | FUTURE | TODAY | OVERDUE
-----------------------------------------------
T0001 | 3 | 1 | 2 | 0
T0002 | 2 | 0 | 0 | 2
T0003 | 1 | 1 | 0 | 0


Is there a way to combine both and combine the results, giving me TOTALS_ALL, FUTURE_TOTALS, OVERDUE_TOTALS, TODAY_TOTALS where these are the sums when status is not considered for the GROUP BY




TASK_CD | STATUS | TOTALS | FUTURE | TODAY | OVERDUE| TOTALS_ALL | FUTURE_TOTAL | TODAY_TOTAL | OVERDUE_TOTAL
T0001 | NW | 1 | 1 | 0 | 0 | 3 | 1
| 2 | 0
T0001 | IP | 1 | 0 | 1 | 0 | 3 | 1
| 2 | 0
T0001 | AG | 1 | 0 | 1 | 0 | 3 | 1
| 2 | 0
T0002 | NW | 2 | 0 | 0 | 2 | 2 | 0
| 0 | 2
T0003 | AG | 1 | 1 | 0 | 0 | 1 | 1
| 0 | 0









share|improve this question
























  • Although it will not give you the same structure, as you've shown you expect, you could consider using ROLLUP (or for more complex cases CUBE) clause for GROUP BY - it is designed to calculate totals and sub-totals.
    – Hilarion
    Nov 19 at 23:26













up vote
1
down vote

favorite









up vote
1
down vote

favorite











This is the table I have.




TASK_CD | STATUS | DUE_DATE
----------------------------------
T0001 | NW | SYSDATE + 1
T0001 | IP | SYSDATE
T0001 | AG | SYSDATE
T0002 | NW | SYSDATE - 1
T0002 | NW | SYSDATE - 2
T0003 | AG | SYSDATE + 1


This is the query I have right now



select TASK_CD, STATUS, SUM(1) TOTALS, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) FUTURE,
SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) TODAY,
SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) OVERDUE,
FROM TM_TASK GROUP BY TASK_CD, STATUS;


result will be




TASK_CD | STATUS | TOTALS | FUTURE | TODAY | OVERDUE
----------------------------------------------------
T0001 | NW | 1 | 1 | 0 | 0
T0001 | IP | 1 | 0 | 1 | 0
T0001 | AG | 1 | 0 | 1 | 0
T0002 | NW | 2 | 0 | 0 | 2
T0003 | AG | 1 | 1 | 0 | 0


By removing STATUS from select and group, I get




TASK_CD | TOTALS | FUTURE | TODAY | OVERDUE
-----------------------------------------------
T0001 | 3 | 1 | 2 | 0
T0002 | 2 | 0 | 0 | 2
T0003 | 1 | 1 | 0 | 0


Is there a way to combine both and combine the results, giving me TOTALS_ALL, FUTURE_TOTALS, OVERDUE_TOTALS, TODAY_TOTALS where these are the sums when status is not considered for the GROUP BY




TASK_CD | STATUS | TOTALS | FUTURE | TODAY | OVERDUE| TOTALS_ALL | FUTURE_TOTAL | TODAY_TOTAL | OVERDUE_TOTAL
T0001 | NW | 1 | 1 | 0 | 0 | 3 | 1
| 2 | 0
T0001 | IP | 1 | 0 | 1 | 0 | 3 | 1
| 2 | 0
T0001 | AG | 1 | 0 | 1 | 0 | 3 | 1
| 2 | 0
T0002 | NW | 2 | 0 | 0 | 2 | 2 | 0
| 0 | 2
T0003 | AG | 1 | 1 | 0 | 0 | 1 | 1
| 0 | 0









share|improve this question















This is the table I have.




TASK_CD | STATUS | DUE_DATE
----------------------------------
T0001 | NW | SYSDATE + 1
T0001 | IP | SYSDATE
T0001 | AG | SYSDATE
T0002 | NW | SYSDATE - 1
T0002 | NW | SYSDATE - 2
T0003 | AG | SYSDATE + 1


This is the query I have right now



select TASK_CD, STATUS, SUM(1) TOTALS, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) FUTURE,
SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) TODAY,
SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) OVERDUE,
FROM TM_TASK GROUP BY TASK_CD, STATUS;


result will be




TASK_CD | STATUS | TOTALS | FUTURE | TODAY | OVERDUE
----------------------------------------------------
T0001 | NW | 1 | 1 | 0 | 0
T0001 | IP | 1 | 0 | 1 | 0
T0001 | AG | 1 | 0 | 1 | 0
T0002 | NW | 2 | 0 | 0 | 2
T0003 | AG | 1 | 1 | 0 | 0


By removing STATUS from select and group, I get




TASK_CD | TOTALS | FUTURE | TODAY | OVERDUE
-----------------------------------------------
T0001 | 3 | 1 | 2 | 0
T0002 | 2 | 0 | 0 | 2
T0003 | 1 | 1 | 0 | 0


Is there a way to combine both and combine the results, giving me TOTALS_ALL, FUTURE_TOTALS, OVERDUE_TOTALS, TODAY_TOTALS where these are the sums when status is not considered for the GROUP BY




TASK_CD | STATUS | TOTALS | FUTURE | TODAY | OVERDUE| TOTALS_ALL | FUTURE_TOTAL | TODAY_TOTAL | OVERDUE_TOTAL
T0001 | NW | 1 | 1 | 0 | 0 | 3 | 1
| 2 | 0
T0001 | IP | 1 | 0 | 1 | 0 | 3 | 1
| 2 | 0
T0001 | AG | 1 | 0 | 1 | 0 | 3 | 1
| 2 | 0
T0002 | NW | 2 | 0 | 0 | 2 | 2 | 0
| 0 | 2
T0003 | AG | 1 | 1 | 0 | 0 | 1 | 1
| 0 | 0






sql oracle oracle11g






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 19 at 20:35









Ben

40.6k2292118




40.6k2292118










asked Nov 19 at 19:49









Sitaram Vuppala

163




163












  • Although it will not give you the same structure, as you've shown you expect, you could consider using ROLLUP (or for more complex cases CUBE) clause for GROUP BY - it is designed to calculate totals and sub-totals.
    – Hilarion
    Nov 19 at 23:26


















  • Although it will not give you the same structure, as you've shown you expect, you could consider using ROLLUP (or for more complex cases CUBE) clause for GROUP BY - it is designed to calculate totals and sub-totals.
    – Hilarion
    Nov 19 at 23:26
















Although it will not give you the same structure, as you've shown you expect, you could consider using ROLLUP (or for more complex cases CUBE) clause for GROUP BY - it is designed to calculate totals and sub-totals.
– Hilarion
Nov 19 at 23:26




Although it will not give you the same structure, as you've shown you expect, you could consider using ROLLUP (or for more complex cases CUBE) clause for GROUP BY - it is designed to calculate totals and sub-totals.
– Hilarion
Nov 19 at 23:26












2 Answers
2






active

oldest

votes

















up vote
2
down vote













You can use the subquery factoring clause (more commonly called a common table expresssion) to generate your initial data set and then an analytic SUM() to aggregate



with initial_totals as (
select task_cd
, status
, count(*) as totals
, sum(case when due_date >= trunc(sysdate) + 1 then 1 else 0 end) as future
, sum(case when trunc(due_date) = trunc(sysdate) then 1 else 0 end) as today
, sum(case when due_date < trunc(sysdate) then 1 else 0 end) as overdue
from tm_task
group by task_cd, status
)
select task_cd
, status
, future
, today
, overdue
, sum(future) over (partition by task_cd) as future_total
, sum(today) over (partition by task_cd) as today_total
, sum(overdue) over (partition by task_cd) as overdue_total
from initial_totals


This is your original query (modified slightly see below) and then an analytic sum over each task code. An analytic sum is the same as an aggregate, but without putting the result against each row.



You can see this in action on db<>fiddle.



You'll note I've changed your date logic. This is because TRUNC(DUE_DATE ) > SYSDATE is the same as saying when midnight today is greater than this second. I've changed this to due_date >= trunc(sysdate) + 1, which is when this second is at or after midnight tomorrow. I've changed all the date logic in a similar manner.






share|improve this answer





















  • It'd be beneficial to know, why the move of TRUNC can be good. For those cases, it'd also be good to show how to do the same for the current day DUE_DATE, not just past/future.
    – Hilarion
    Nov 19 at 23:33










  • Hi @Hilarion; to be honest that hurts a bit. You're criticising the correct answer with the explanation rather than the incorrect (not just dates the SQL logic too) without an explanation. I have explained why moving TRUNC() is good as well as I know how. I haven't used the word "move" it's true, but it's not actually moving a function, it's a different logical construct. If you don't understand the explanation can you tell me what you don't understand so I can improve my explanation?
    – Ben
    Nov 20 at 6:03










  • Thank you @Ben. My only dilemma is which is a better approach your or Gordon. I tried doing the explain plan and the cost for both queries is similar. On running them both I time it was taking is similar as well. But my local db has limited test data. I have to see how they perform with huge loads.
    – Sitaram Vuppala
    Nov 20 at 14:50










  • They're basically the same query @Sitaram, I don't think there'll be any difference with large amouns of data. Have you checked that the data returned is correct in both? Either can be modified to return the correct data but it looks like we've interpreted your question slightly different.
    – Ben
    Nov 20 at 18:45










  • Yes, I was able to get the expected results...Thank you :)
    – Sitaram Vuppala
    Nov 20 at 18:46


















up vote
2
down vote













You would use window functions:



select TASK_CD, STATUS, SUM(1) TOTALS, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) as FUTURE,
SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) as TODAY,
SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) as OVERDUE,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_FUTURE,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_TODAY,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_OVERDUE
FROM TM_TASK
GROUP BY TASK_CD, STATUS;





share|improve this answer





















  • Hi, I have already tried partitioning, it was giving "ORA-00937: not a single-group group function" exception
    – Sitaram Vuppala
    Nov 19 at 22:42






  • 2




    Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?
    – Hilarion
    Nov 19 at 23:27










  • Thank you @GordonLinoff. Yes I missed the double sum use.
    – Sitaram Vuppala
    Nov 20 at 14:33











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53381663%2fsubtotals-of-a-group-by-in-oracle%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
2
down vote













You can use the subquery factoring clause (more commonly called a common table expresssion) to generate your initial data set and then an analytic SUM() to aggregate



with initial_totals as (
select task_cd
, status
, count(*) as totals
, sum(case when due_date >= trunc(sysdate) + 1 then 1 else 0 end) as future
, sum(case when trunc(due_date) = trunc(sysdate) then 1 else 0 end) as today
, sum(case when due_date < trunc(sysdate) then 1 else 0 end) as overdue
from tm_task
group by task_cd, status
)
select task_cd
, status
, future
, today
, overdue
, sum(future) over (partition by task_cd) as future_total
, sum(today) over (partition by task_cd) as today_total
, sum(overdue) over (partition by task_cd) as overdue_total
from initial_totals


This is your original query (modified slightly see below) and then an analytic sum over each task code. An analytic sum is the same as an aggregate, but without putting the result against each row.



You can see this in action on db<>fiddle.



You'll note I've changed your date logic. This is because TRUNC(DUE_DATE ) > SYSDATE is the same as saying when midnight today is greater than this second. I've changed this to due_date >= trunc(sysdate) + 1, which is when this second is at or after midnight tomorrow. I've changed all the date logic in a similar manner.






share|improve this answer





















  • It'd be beneficial to know, why the move of TRUNC can be good. For those cases, it'd also be good to show how to do the same for the current day DUE_DATE, not just past/future.
    – Hilarion
    Nov 19 at 23:33










  • Hi @Hilarion; to be honest that hurts a bit. You're criticising the correct answer with the explanation rather than the incorrect (not just dates the SQL logic too) without an explanation. I have explained why moving TRUNC() is good as well as I know how. I haven't used the word "move" it's true, but it's not actually moving a function, it's a different logical construct. If you don't understand the explanation can you tell me what you don't understand so I can improve my explanation?
    – Ben
    Nov 20 at 6:03










  • Thank you @Ben. My only dilemma is which is a better approach your or Gordon. I tried doing the explain plan and the cost for both queries is similar. On running them both I time it was taking is similar as well. But my local db has limited test data. I have to see how they perform with huge loads.
    – Sitaram Vuppala
    Nov 20 at 14:50










  • They're basically the same query @Sitaram, I don't think there'll be any difference with large amouns of data. Have you checked that the data returned is correct in both? Either can be modified to return the correct data but it looks like we've interpreted your question slightly different.
    – Ben
    Nov 20 at 18:45










  • Yes, I was able to get the expected results...Thank you :)
    – Sitaram Vuppala
    Nov 20 at 18:46















up vote
2
down vote













You can use the subquery factoring clause (more commonly called a common table expresssion) to generate your initial data set and then an analytic SUM() to aggregate



with initial_totals as (
select task_cd
, status
, count(*) as totals
, sum(case when due_date >= trunc(sysdate) + 1 then 1 else 0 end) as future
, sum(case when trunc(due_date) = trunc(sysdate) then 1 else 0 end) as today
, sum(case when due_date < trunc(sysdate) then 1 else 0 end) as overdue
from tm_task
group by task_cd, status
)
select task_cd
, status
, future
, today
, overdue
, sum(future) over (partition by task_cd) as future_total
, sum(today) over (partition by task_cd) as today_total
, sum(overdue) over (partition by task_cd) as overdue_total
from initial_totals


This is your original query (modified slightly see below) and then an analytic sum over each task code. An analytic sum is the same as an aggregate, but without putting the result against each row.



You can see this in action on db<>fiddle.



You'll note I've changed your date logic. This is because TRUNC(DUE_DATE ) > SYSDATE is the same as saying when midnight today is greater than this second. I've changed this to due_date >= trunc(sysdate) + 1, which is when this second is at or after midnight tomorrow. I've changed all the date logic in a similar manner.






share|improve this answer





















  • It'd be beneficial to know, why the move of TRUNC can be good. For those cases, it'd also be good to show how to do the same for the current day DUE_DATE, not just past/future.
    – Hilarion
    Nov 19 at 23:33










  • Hi @Hilarion; to be honest that hurts a bit. You're criticising the correct answer with the explanation rather than the incorrect (not just dates the SQL logic too) without an explanation. I have explained why moving TRUNC() is good as well as I know how. I haven't used the word "move" it's true, but it's not actually moving a function, it's a different logical construct. If you don't understand the explanation can you tell me what you don't understand so I can improve my explanation?
    – Ben
    Nov 20 at 6:03










  • Thank you @Ben. My only dilemma is which is a better approach your or Gordon. I tried doing the explain plan and the cost for both queries is similar. On running them both I time it was taking is similar as well. But my local db has limited test data. I have to see how they perform with huge loads.
    – Sitaram Vuppala
    Nov 20 at 14:50










  • They're basically the same query @Sitaram, I don't think there'll be any difference with large amouns of data. Have you checked that the data returned is correct in both? Either can be modified to return the correct data but it looks like we've interpreted your question slightly different.
    – Ben
    Nov 20 at 18:45










  • Yes, I was able to get the expected results...Thank you :)
    – Sitaram Vuppala
    Nov 20 at 18:46













up vote
2
down vote










up vote
2
down vote









You can use the subquery factoring clause (more commonly called a common table expresssion) to generate your initial data set and then an analytic SUM() to aggregate



with initial_totals as (
select task_cd
, status
, count(*) as totals
, sum(case when due_date >= trunc(sysdate) + 1 then 1 else 0 end) as future
, sum(case when trunc(due_date) = trunc(sysdate) then 1 else 0 end) as today
, sum(case when due_date < trunc(sysdate) then 1 else 0 end) as overdue
from tm_task
group by task_cd, status
)
select task_cd
, status
, future
, today
, overdue
, sum(future) over (partition by task_cd) as future_total
, sum(today) over (partition by task_cd) as today_total
, sum(overdue) over (partition by task_cd) as overdue_total
from initial_totals


This is your original query (modified slightly see below) and then an analytic sum over each task code. An analytic sum is the same as an aggregate, but without putting the result against each row.



You can see this in action on db<>fiddle.



You'll note I've changed your date logic. This is because TRUNC(DUE_DATE ) > SYSDATE is the same as saying when midnight today is greater than this second. I've changed this to due_date >= trunc(sysdate) + 1, which is when this second is at or after midnight tomorrow. I've changed all the date logic in a similar manner.






share|improve this answer












You can use the subquery factoring clause (more commonly called a common table expresssion) to generate your initial data set and then an analytic SUM() to aggregate



with initial_totals as (
select task_cd
, status
, count(*) as totals
, sum(case when due_date >= trunc(sysdate) + 1 then 1 else 0 end) as future
, sum(case when trunc(due_date) = trunc(sysdate) then 1 else 0 end) as today
, sum(case when due_date < trunc(sysdate) then 1 else 0 end) as overdue
from tm_task
group by task_cd, status
)
select task_cd
, status
, future
, today
, overdue
, sum(future) over (partition by task_cd) as future_total
, sum(today) over (partition by task_cd) as today_total
, sum(overdue) over (partition by task_cd) as overdue_total
from initial_totals


This is your original query (modified slightly see below) and then an analytic sum over each task code. An analytic sum is the same as an aggregate, but without putting the result against each row.



You can see this in action on db<>fiddle.



You'll note I've changed your date logic. This is because TRUNC(DUE_DATE ) > SYSDATE is the same as saying when midnight today is greater than this second. I've changed this to due_date >= trunc(sysdate) + 1, which is when this second is at or after midnight tomorrow. I've changed all the date logic in a similar manner.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 19 at 20:28









Ben

40.6k2292118




40.6k2292118












  • It'd be beneficial to know, why the move of TRUNC can be good. For those cases, it'd also be good to show how to do the same for the current day DUE_DATE, not just past/future.
    – Hilarion
    Nov 19 at 23:33










  • Hi @Hilarion; to be honest that hurts a bit. You're criticising the correct answer with the explanation rather than the incorrect (not just dates the SQL logic too) without an explanation. I have explained why moving TRUNC() is good as well as I know how. I haven't used the word "move" it's true, but it's not actually moving a function, it's a different logical construct. If you don't understand the explanation can you tell me what you don't understand so I can improve my explanation?
    – Ben
    Nov 20 at 6:03










  • Thank you @Ben. My only dilemma is which is a better approach your or Gordon. I tried doing the explain plan and the cost for both queries is similar. On running them both I time it was taking is similar as well. But my local db has limited test data. I have to see how they perform with huge loads.
    – Sitaram Vuppala
    Nov 20 at 14:50










  • They're basically the same query @Sitaram, I don't think there'll be any difference with large amouns of data. Have you checked that the data returned is correct in both? Either can be modified to return the correct data but it looks like we've interpreted your question slightly different.
    – Ben
    Nov 20 at 18:45










  • Yes, I was able to get the expected results...Thank you :)
    – Sitaram Vuppala
    Nov 20 at 18:46


















  • It'd be beneficial to know, why the move of TRUNC can be good. For those cases, it'd also be good to show how to do the same for the current day DUE_DATE, not just past/future.
    – Hilarion
    Nov 19 at 23:33










  • Hi @Hilarion; to be honest that hurts a bit. You're criticising the correct answer with the explanation rather than the incorrect (not just dates the SQL logic too) without an explanation. I have explained why moving TRUNC() is good as well as I know how. I haven't used the word "move" it's true, but it's not actually moving a function, it's a different logical construct. If you don't understand the explanation can you tell me what you don't understand so I can improve my explanation?
    – Ben
    Nov 20 at 6:03










  • Thank you @Ben. My only dilemma is which is a better approach your or Gordon. I tried doing the explain plan and the cost for both queries is similar. On running them both I time it was taking is similar as well. But my local db has limited test data. I have to see how they perform with huge loads.
    – Sitaram Vuppala
    Nov 20 at 14:50










  • They're basically the same query @Sitaram, I don't think there'll be any difference with large amouns of data. Have you checked that the data returned is correct in both? Either can be modified to return the correct data but it looks like we've interpreted your question slightly different.
    – Ben
    Nov 20 at 18:45










  • Yes, I was able to get the expected results...Thank you :)
    – Sitaram Vuppala
    Nov 20 at 18:46
















It'd be beneficial to know, why the move of TRUNC can be good. For those cases, it'd also be good to show how to do the same for the current day DUE_DATE, not just past/future.
– Hilarion
Nov 19 at 23:33




It'd be beneficial to know, why the move of TRUNC can be good. For those cases, it'd also be good to show how to do the same for the current day DUE_DATE, not just past/future.
– Hilarion
Nov 19 at 23:33












Hi @Hilarion; to be honest that hurts a bit. You're criticising the correct answer with the explanation rather than the incorrect (not just dates the SQL logic too) without an explanation. I have explained why moving TRUNC() is good as well as I know how. I haven't used the word "move" it's true, but it's not actually moving a function, it's a different logical construct. If you don't understand the explanation can you tell me what you don't understand so I can improve my explanation?
– Ben
Nov 20 at 6:03




Hi @Hilarion; to be honest that hurts a bit. You're criticising the correct answer with the explanation rather than the incorrect (not just dates the SQL logic too) without an explanation. I have explained why moving TRUNC() is good as well as I know how. I haven't used the word "move" it's true, but it's not actually moving a function, it's a different logical construct. If you don't understand the explanation can you tell me what you don't understand so I can improve my explanation?
– Ben
Nov 20 at 6:03












Thank you @Ben. My only dilemma is which is a better approach your or Gordon. I tried doing the explain plan and the cost for both queries is similar. On running them both I time it was taking is similar as well. But my local db has limited test data. I have to see how they perform with huge loads.
– Sitaram Vuppala
Nov 20 at 14:50




Thank you @Ben. My only dilemma is which is a better approach your or Gordon. I tried doing the explain plan and the cost for both queries is similar. On running them both I time it was taking is similar as well. But my local db has limited test data. I have to see how they perform with huge loads.
– Sitaram Vuppala
Nov 20 at 14:50












They're basically the same query @Sitaram, I don't think there'll be any difference with large amouns of data. Have you checked that the data returned is correct in both? Either can be modified to return the correct data but it looks like we've interpreted your question slightly different.
– Ben
Nov 20 at 18:45




They're basically the same query @Sitaram, I don't think there'll be any difference with large amouns of data. Have you checked that the data returned is correct in both? Either can be modified to return the correct data but it looks like we've interpreted your question slightly different.
– Ben
Nov 20 at 18:45












Yes, I was able to get the expected results...Thank you :)
– Sitaram Vuppala
Nov 20 at 18:46




Yes, I was able to get the expected results...Thank you :)
– Sitaram Vuppala
Nov 20 at 18:46












up vote
2
down vote













You would use window functions:



select TASK_CD, STATUS, SUM(1) TOTALS, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) as FUTURE,
SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) as TODAY,
SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) as OVERDUE,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_FUTURE,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_TODAY,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_OVERDUE
FROM TM_TASK
GROUP BY TASK_CD, STATUS;





share|improve this answer





















  • Hi, I have already tried partitioning, it was giving "ORA-00937: not a single-group group function" exception
    – Sitaram Vuppala
    Nov 19 at 22:42






  • 2




    Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?
    – Hilarion
    Nov 19 at 23:27










  • Thank you @GordonLinoff. Yes I missed the double sum use.
    – Sitaram Vuppala
    Nov 20 at 14:33















up vote
2
down vote













You would use window functions:



select TASK_CD, STATUS, SUM(1) TOTALS, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) as FUTURE,
SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) as TODAY,
SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) as OVERDUE,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_FUTURE,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_TODAY,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_OVERDUE
FROM TM_TASK
GROUP BY TASK_CD, STATUS;





share|improve this answer





















  • Hi, I have already tried partitioning, it was giving "ORA-00937: not a single-group group function" exception
    – Sitaram Vuppala
    Nov 19 at 22:42






  • 2




    Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?
    – Hilarion
    Nov 19 at 23:27










  • Thank you @GordonLinoff. Yes I missed the double sum use.
    – Sitaram Vuppala
    Nov 20 at 14:33













up vote
2
down vote










up vote
2
down vote









You would use window functions:



select TASK_CD, STATUS, SUM(1) TOTALS, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) as FUTURE,
SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) as TODAY,
SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) as OVERDUE,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_FUTURE,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_TODAY,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_OVERDUE
FROM TM_TASK
GROUP BY TASK_CD, STATUS;





share|improve this answer












You would use window functions:



select TASK_CD, STATUS, SUM(1) TOTALS, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) as FUTURE,
SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) as TODAY,
SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) as OVERDUE,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_FUTURE,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_TODAY,
SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_OVERDUE
FROM TM_TASK
GROUP BY TASK_CD, STATUS;






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 19 at 20:51









Gordon Linoff

752k34286394




752k34286394












  • Hi, I have already tried partitioning, it was giving "ORA-00937: not a single-group group function" exception
    – Sitaram Vuppala
    Nov 19 at 22:42






  • 2




    Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?
    – Hilarion
    Nov 19 at 23:27










  • Thank you @GordonLinoff. Yes I missed the double sum use.
    – Sitaram Vuppala
    Nov 20 at 14:33


















  • Hi, I have already tried partitioning, it was giving "ORA-00937: not a single-group group function" exception
    – Sitaram Vuppala
    Nov 19 at 22:42






  • 2




    Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?
    – Hilarion
    Nov 19 at 23:27










  • Thank you @GordonLinoff. Yes I missed the double sum use.
    – Sitaram Vuppala
    Nov 20 at 14:33
















Hi, I have already tried partitioning, it was giving "ORA-00937: not a single-group group function" exception
– Sitaram Vuppala
Nov 19 at 22:42




Hi, I have already tried partitioning, it was giving "ORA-00937: not a single-group group function" exception
– Sitaram Vuppala
Nov 19 at 22:42




2




2




Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?
– Hilarion
Nov 19 at 23:27




Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?
– Hilarion
Nov 19 at 23:27












Thank you @GordonLinoff. Yes I missed the double sum use.
– Sitaram Vuppala
Nov 20 at 14:33




Thank you @GordonLinoff. Yes I missed the double sum use.
– Sitaram Vuppala
Nov 20 at 14:33


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53381663%2fsubtotals-of-a-group-by-in-oracle%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Create new schema in PostgreSQL using DBeaver

Deepest pit of an array with Javascript: test on Codility

Costa Masnaga