SUBTOTALS of a GROUP BY IN ORACLE












1















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 '18 at 23:26
















1















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 '18 at 23:26














1












1








1








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 '18 at 20:35









Ben

41.1k2294119




41.1k2294119










asked Nov 19 '18 at 19:49









Sitaram VuppalaSitaram 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 '18 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 '18 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 '18 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 '18 at 23:26












2 Answers
2






active

oldest

votes


















2














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 '18 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 '18 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 '18 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 '18 at 18:45











  • Yes, I was able to get the expected results...Thank you :)

    – Sitaram Vuppala
    Nov 20 '18 at 18:46



















2














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 '18 at 22:42






  • 2





    Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?

    – Hilarion
    Nov 19 '18 at 23:27











  • Thank you @GordonLinoff. Yes I missed the double sum use.

    – Sitaram Vuppala
    Nov 20 '18 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',
autoActivateHeartbeat: false,
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









2














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 '18 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 '18 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 '18 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 '18 at 18:45











  • Yes, I was able to get the expected results...Thank you :)

    – Sitaram Vuppala
    Nov 20 '18 at 18:46
















2














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 '18 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 '18 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 '18 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 '18 at 18:45











  • Yes, I was able to get the expected results...Thank you :)

    – Sitaram Vuppala
    Nov 20 '18 at 18:46














2












2








2







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 '18 at 20:28









BenBen

41.1k2294119




41.1k2294119













  • 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 '18 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 '18 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 '18 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 '18 at 18:45











  • Yes, I was able to get the expected results...Thank you :)

    – Sitaram Vuppala
    Nov 20 '18 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 '18 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 '18 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 '18 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 '18 at 18:45











  • Yes, I was able to get the expected results...Thank you :)

    – Sitaram Vuppala
    Nov 20 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 at 18:45













Yes, I was able to get the expected results...Thank you :)

– Sitaram Vuppala
Nov 20 '18 at 18:46





Yes, I was able to get the expected results...Thank you :)

– Sitaram Vuppala
Nov 20 '18 at 18:46













2














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 '18 at 22:42






  • 2





    Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?

    – Hilarion
    Nov 19 '18 at 23:27











  • Thank you @GordonLinoff. Yes I missed the double sum use.

    – Sitaram Vuppala
    Nov 20 '18 at 14:33
















2














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 '18 at 22:42






  • 2





    Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?

    – Hilarion
    Nov 19 '18 at 23:27











  • Thank you @GordonLinoff. Yes I missed the double sum use.

    – Sitaram Vuppala
    Nov 20 '18 at 14:33














2












2








2







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 '18 at 20:51









Gordon LinoffGordon Linoff

774k35306408




774k35306408













  • Hi, I have already tried partitioning, it was giving "ORA-00937: not a single-group group function" exception

    – Sitaram Vuppala
    Nov 19 '18 at 22:42






  • 2





    Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?

    – Hilarion
    Nov 19 '18 at 23:27











  • Thank you @GordonLinoff. Yes I missed the double sum use.

    – Sitaram Vuppala
    Nov 20 '18 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 '18 at 22:42






  • 2





    Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?

    – Hilarion
    Nov 19 '18 at 23:27











  • Thank you @GordonLinoff. Yes I missed the double sum use.

    – Sitaram Vuppala
    Nov 20 '18 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 '18 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 '18 at 22:42




2




2





Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?

– Hilarion
Nov 19 '18 at 23:27





Try it as @GordonLinoff described - it should work. Maybe you've missed the double SUM use?

– Hilarion
Nov 19 '18 at 23:27













Thank you @GordonLinoff. Yes I missed the double sum use.

– Sitaram Vuppala
Nov 20 '18 at 14:33





Thank you @GordonLinoff. Yes I missed the double sum use.

– Sitaram Vuppala
Nov 20 '18 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.




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

Guess what letter conforming each word

Port of Spain

Run scheduled task as local user group (not BUILTIN)