SUBTOTALS of a GROUP BY IN ORACLE
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
add a comment |
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
Although it will not give you the same structure, as you've shown you expect, you could consider usingROLLUP
(or for more complex casesCUBE
) clause forGROUP BY
- it is designed to calculate totals and sub-totals.
– Hilarion
Nov 19 '18 at 23:26
add a comment |
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
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
sql oracle oracle11g
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 usingROLLUP
(or for more complex casesCUBE
) clause forGROUP BY
- it is designed to calculate totals and sub-totals.
– Hilarion
Nov 19 '18 at 23:26
add a comment |
Although it will not give you the same structure, as you've shown you expect, you could consider usingROLLUP
(or for more complex casesCUBE
) clause forGROUP 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
add a comment |
2 Answers
2
active
oldest
votes
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.
It'd be beneficial to know, why the move ofTRUNC
can be good. For those cases, it'd also be good to show how to do the same for the current dayDUE_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 movingTRUNC()
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
|
show 1 more comment
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;
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 doubleSUM
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
It'd be beneficial to know, why the move ofTRUNC
can be good. For those cases, it'd also be good to show how to do the same for the current dayDUE_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 movingTRUNC()
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
|
show 1 more comment
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.
It'd be beneficial to know, why the move ofTRUNC
can be good. For those cases, it'd also be good to show how to do the same for the current dayDUE_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 movingTRUNC()
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
|
show 1 more comment
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.
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.
answered Nov 19 '18 at 20:28
BenBen
41.1k2294119
41.1k2294119
It'd be beneficial to know, why the move ofTRUNC
can be good. For those cases, it'd also be good to show how to do the same for the current dayDUE_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 movingTRUNC()
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
|
show 1 more comment
It'd be beneficial to know, why the move ofTRUNC
can be good. For those cases, it'd also be good to show how to do the same for the current dayDUE_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 movingTRUNC()
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
|
show 1 more comment
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;
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 doubleSUM
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
add a comment |
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;
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 doubleSUM
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
add a comment |
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;
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;
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 doubleSUM
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
add a comment |
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 doubleSUM
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
Although it will not give you the same structure, as you've shown you expect, you could consider using
ROLLUP
(or for more complex casesCUBE
) clause forGROUP BY
- it is designed to calculate totals and sub-totals.– Hilarion
Nov 19 '18 at 23:26