PLSQL : where condition outside of subquery
I've a query like this (the original is much more complicated)
select 0, 999, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between 0 and 999
union
select 1000, 2999, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between 1000 and 2999
union
...
There are multiple union and the select is way more complicated.
I'd like to simplify it. For this, I used the with clause
with q1 as(
select case when cond = 'aa' then 1 end val1, case when cond = 'aa' then amount else 0 end amount1,
case when cond = 'bb' then 1 end val2, case when cond = 'bb' then amount else 0 end amount2
)
select 0, 999, sum(val1) val1, sum(amount1) amount1, sum(val2) val2, sum(amount2) amount2
from q1 where amount between 0 and 999
union
select 1000, 2999, sum(val1) val1, sum(amount1) amount1, sum(val2) val2, sum(amount2) amount2
from q1 where amount between 1000 and 2999
union
....
But in my case this is still very long.
Is there a possibility in plsql to write it like this
with q1 as (
select minVal, maxVal, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between minVal and maxVal
)
select * from q1 insideWhere minVal=0 and maxVal=999
union select * from q1 insideWhere minVal=1000 and maxVal=2999
union ...
Or any other solution?
sql oracle subquery
add a comment |
I've a query like this (the original is much more complicated)
select 0, 999, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between 0 and 999
union
select 1000, 2999, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between 1000 and 2999
union
...
There are multiple union and the select is way more complicated.
I'd like to simplify it. For this, I used the with clause
with q1 as(
select case when cond = 'aa' then 1 end val1, case when cond = 'aa' then amount else 0 end amount1,
case when cond = 'bb' then 1 end val2, case when cond = 'bb' then amount else 0 end amount2
)
select 0, 999, sum(val1) val1, sum(amount1) amount1, sum(val2) val2, sum(amount2) amount2
from q1 where amount between 0 and 999
union
select 1000, 2999, sum(val1) val1, sum(amount1) amount1, sum(val2) val2, sum(amount2) amount2
from q1 where amount between 1000 and 2999
union
....
But in my case this is still very long.
Is there a possibility in plsql to write it like this
with q1 as (
select minVal, maxVal, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between minVal and maxVal
)
select * from q1 insideWhere minVal=0 and maxVal=999
union select * from q1 insideWhere minVal=1000 and maxVal=2999
union ...
Or any other solution?
sql oracle subquery
1
You could probably get some better answers, if you'd describe your real problem in more detail. I.e. what problem is the original query addressing? That way we may be able to give you better alternatives, than just blindly trying to follow your only direction (which may not necessarily be the the best, if possible at all).
– Hilarion
Nov 23 '18 at 12:39
it's about the same as the first query but with the (case when cond = 'aa' then 1 end) with more complicated conditions and with more than 20 case and even more union Further more the number of steps (between x an y) will change depending what is asked and my table is already the result of a with clause
– user1753180
Nov 23 '18 at 13:21
add a comment |
I've a query like this (the original is much more complicated)
select 0, 999, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between 0 and 999
union
select 1000, 2999, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between 1000 and 2999
union
...
There are multiple union and the select is way more complicated.
I'd like to simplify it. For this, I used the with clause
with q1 as(
select case when cond = 'aa' then 1 end val1, case when cond = 'aa' then amount else 0 end amount1,
case when cond = 'bb' then 1 end val2, case when cond = 'bb' then amount else 0 end amount2
)
select 0, 999, sum(val1) val1, sum(amount1) amount1, sum(val2) val2, sum(amount2) amount2
from q1 where amount between 0 and 999
union
select 1000, 2999, sum(val1) val1, sum(amount1) amount1, sum(val2) val2, sum(amount2) amount2
from q1 where amount between 1000 and 2999
union
....
But in my case this is still very long.
Is there a possibility in plsql to write it like this
with q1 as (
select minVal, maxVal, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between minVal and maxVal
)
select * from q1 insideWhere minVal=0 and maxVal=999
union select * from q1 insideWhere minVal=1000 and maxVal=2999
union ...
Or any other solution?
sql oracle subquery
I've a query like this (the original is much more complicated)
select 0, 999, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between 0 and 999
union
select 1000, 2999, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between 1000 and 2999
union
...
There are multiple union and the select is way more complicated.
I'd like to simplify it. For this, I used the with clause
with q1 as(
select case when cond = 'aa' then 1 end val1, case when cond = 'aa' then amount else 0 end amount1,
case when cond = 'bb' then 1 end val2, case when cond = 'bb' then amount else 0 end amount2
)
select 0, 999, sum(val1) val1, sum(amount1) amount1, sum(val2) val2, sum(amount2) amount2
from q1 where amount between 0 and 999
union
select 1000, 2999, sum(val1) val1, sum(amount1) amount1, sum(val2) val2, sum(amount2) amount2
from q1 where amount between 1000 and 2999
union
....
But in my case this is still very long.
Is there a possibility in plsql to write it like this
with q1 as (
select minVal, maxVal, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between minVal and maxVal
)
select * from q1 insideWhere minVal=0 and maxVal=999
union select * from q1 insideWhere minVal=1000 and maxVal=2999
union ...
Or any other solution?
sql oracle subquery
sql oracle subquery
edited Nov 23 '18 at 13:22
a_horse_with_no_name
292k46447541
292k46447541
asked Nov 23 '18 at 12:33
user1753180user1753180
3015
3015
1
You could probably get some better answers, if you'd describe your real problem in more detail. I.e. what problem is the original query addressing? That way we may be able to give you better alternatives, than just blindly trying to follow your only direction (which may not necessarily be the the best, if possible at all).
– Hilarion
Nov 23 '18 at 12:39
it's about the same as the first query but with the (case when cond = 'aa' then 1 end) with more complicated conditions and with more than 20 case and even more union Further more the number of steps (between x an y) will change depending what is asked and my table is already the result of a with clause
– user1753180
Nov 23 '18 at 13:21
add a comment |
1
You could probably get some better answers, if you'd describe your real problem in more detail. I.e. what problem is the original query addressing? That way we may be able to give you better alternatives, than just blindly trying to follow your only direction (which may not necessarily be the the best, if possible at all).
– Hilarion
Nov 23 '18 at 12:39
it's about the same as the first query but with the (case when cond = 'aa' then 1 end) with more complicated conditions and with more than 20 case and even more union Further more the number of steps (between x an y) will change depending what is asked and my table is already the result of a with clause
– user1753180
Nov 23 '18 at 13:21
1
1
You could probably get some better answers, if you'd describe your real problem in more detail. I.e. what problem is the original query addressing? That way we may be able to give you better alternatives, than just blindly trying to follow your only direction (which may not necessarily be the the best, if possible at all).
– Hilarion
Nov 23 '18 at 12:39
You could probably get some better answers, if you'd describe your real problem in more detail. I.e. what problem is the original query addressing? That way we may be able to give you better alternatives, than just blindly trying to follow your only direction (which may not necessarily be the the best, if possible at all).
– Hilarion
Nov 23 '18 at 12:39
it's about the same as the first query but with the (case when cond = 'aa' then 1 end) with more complicated conditions and with more than 20 case and even more union Further more the number of steps (between x an y) will change depending what is asked and my table is already the result of a with clause
– user1753180
Nov 23 '18 at 13:21
it's about the same as the first query but with the (case when cond = 'aa' then 1 end) with more complicated conditions and with more than 20 case and even more union Further more the number of steps (between x an y) will change depending what is asked and my table is already the result of a with clause
– user1753180
Nov 23 '18 at 13:21
add a comment |
2 Answers
2
active
oldest
votes
This sounds like it should be a single aggregate query, e.g.:
SELECT min_val,
max_val,
COUNT(CASE WHEN cond = 'aa' THEN 1 END) val1,
SUM(CASE WHEN cond = 'aa' THEN amount ELSE 0 END) amount1,
COUNT(CASE WHEN cond = 'bb' THEN 1 END) val2,
SUM(CASE WHEN cond = 'bb' THEN amount ELSE 0 END) amount2,
FROM (SELECT cond,
amount,
CASE WHEN amount BETWEEN 0 AND 999 THEN 0
WHEN amount BETWEEN 1000 AND 2999 THEN 1000
END min_val,
CASE WHEN amount BETWEEN 0 AND 999 THEN 999
WHEN amount BETWEEN 1000 AND 2999 THEN 2999
END max_val
FROM mytable) -- using a subquery here to avoid repeating the case statement in both the select column list and the group by column list
GROUP BY min_val,
max_val;
add a comment |
To do what you're attempting you need to manifest the min/max groups into a table-like structure. You're already most of the way there: the easy way to do this is to use the WITH
clause.
WITH value_groups AS
(SELECT 0 AS min_val, 999 AS max_val FROM DUAL
UNION ALL
SELECT 1000, 2999 FROM DUAL),
q1 AS
(SELECT *
FROM my_table
PIVOT
(COUNT (*) FOR cond IN ('aa' AS aa, 'bb' AS bb)))
SELECT min_val,
max_val,
COUNT (aa) as val1,
SUM (aa * amount) as amount1,
COUNT (bb) as val2,
SUM (bb * amount) as amount2
FROM q1 JOIN value_groups ON amount BETWEEN min_val AND max_val
GROUP BY min_val, max_val
I've also converted your CASE
statements into a pivot. This will group matching sets of count/amount (i.e. if there are two 'aa' rows with an amount of 100, that will be returned as amount=100, count=2), which is why I'm multiplying the two to get the correct sum.
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%2f53446806%2fplsql-where-condition-outside-of-subquery%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
This sounds like it should be a single aggregate query, e.g.:
SELECT min_val,
max_val,
COUNT(CASE WHEN cond = 'aa' THEN 1 END) val1,
SUM(CASE WHEN cond = 'aa' THEN amount ELSE 0 END) amount1,
COUNT(CASE WHEN cond = 'bb' THEN 1 END) val2,
SUM(CASE WHEN cond = 'bb' THEN amount ELSE 0 END) amount2,
FROM (SELECT cond,
amount,
CASE WHEN amount BETWEEN 0 AND 999 THEN 0
WHEN amount BETWEEN 1000 AND 2999 THEN 1000
END min_val,
CASE WHEN amount BETWEEN 0 AND 999 THEN 999
WHEN amount BETWEEN 1000 AND 2999 THEN 2999
END max_val
FROM mytable) -- using a subquery here to avoid repeating the case statement in both the select column list and the group by column list
GROUP BY min_val,
max_val;
add a comment |
This sounds like it should be a single aggregate query, e.g.:
SELECT min_val,
max_val,
COUNT(CASE WHEN cond = 'aa' THEN 1 END) val1,
SUM(CASE WHEN cond = 'aa' THEN amount ELSE 0 END) amount1,
COUNT(CASE WHEN cond = 'bb' THEN 1 END) val2,
SUM(CASE WHEN cond = 'bb' THEN amount ELSE 0 END) amount2,
FROM (SELECT cond,
amount,
CASE WHEN amount BETWEEN 0 AND 999 THEN 0
WHEN amount BETWEEN 1000 AND 2999 THEN 1000
END min_val,
CASE WHEN amount BETWEEN 0 AND 999 THEN 999
WHEN amount BETWEEN 1000 AND 2999 THEN 2999
END max_val
FROM mytable) -- using a subquery here to avoid repeating the case statement in both the select column list and the group by column list
GROUP BY min_val,
max_val;
add a comment |
This sounds like it should be a single aggregate query, e.g.:
SELECT min_val,
max_val,
COUNT(CASE WHEN cond = 'aa' THEN 1 END) val1,
SUM(CASE WHEN cond = 'aa' THEN amount ELSE 0 END) amount1,
COUNT(CASE WHEN cond = 'bb' THEN 1 END) val2,
SUM(CASE WHEN cond = 'bb' THEN amount ELSE 0 END) amount2,
FROM (SELECT cond,
amount,
CASE WHEN amount BETWEEN 0 AND 999 THEN 0
WHEN amount BETWEEN 1000 AND 2999 THEN 1000
END min_val,
CASE WHEN amount BETWEEN 0 AND 999 THEN 999
WHEN amount BETWEEN 1000 AND 2999 THEN 2999
END max_val
FROM mytable) -- using a subquery here to avoid repeating the case statement in both the select column list and the group by column list
GROUP BY min_val,
max_val;
This sounds like it should be a single aggregate query, e.g.:
SELECT min_val,
max_val,
COUNT(CASE WHEN cond = 'aa' THEN 1 END) val1,
SUM(CASE WHEN cond = 'aa' THEN amount ELSE 0 END) amount1,
COUNT(CASE WHEN cond = 'bb' THEN 1 END) val2,
SUM(CASE WHEN cond = 'bb' THEN amount ELSE 0 END) amount2,
FROM (SELECT cond,
amount,
CASE WHEN amount BETWEEN 0 AND 999 THEN 0
WHEN amount BETWEEN 1000 AND 2999 THEN 1000
END min_val,
CASE WHEN amount BETWEEN 0 AND 999 THEN 999
WHEN amount BETWEEN 1000 AND 2999 THEN 2999
END max_val
FROM mytable) -- using a subquery here to avoid repeating the case statement in both the select column list and the group by column list
GROUP BY min_val,
max_val;
edited Dec 16 '18 at 8:35
marc_s
571k12811031252
571k12811031252
answered Nov 23 '18 at 14:11
BoneistBoneist
18k11028
18k11028
add a comment |
add a comment |
To do what you're attempting you need to manifest the min/max groups into a table-like structure. You're already most of the way there: the easy way to do this is to use the WITH
clause.
WITH value_groups AS
(SELECT 0 AS min_val, 999 AS max_val FROM DUAL
UNION ALL
SELECT 1000, 2999 FROM DUAL),
q1 AS
(SELECT *
FROM my_table
PIVOT
(COUNT (*) FOR cond IN ('aa' AS aa, 'bb' AS bb)))
SELECT min_val,
max_val,
COUNT (aa) as val1,
SUM (aa * amount) as amount1,
COUNT (bb) as val2,
SUM (bb * amount) as amount2
FROM q1 JOIN value_groups ON amount BETWEEN min_val AND max_val
GROUP BY min_val, max_val
I've also converted your CASE
statements into a pivot. This will group matching sets of count/amount (i.e. if there are two 'aa' rows with an amount of 100, that will be returned as amount=100, count=2), which is why I'm multiplying the two to get the correct sum.
add a comment |
To do what you're attempting you need to manifest the min/max groups into a table-like structure. You're already most of the way there: the easy way to do this is to use the WITH
clause.
WITH value_groups AS
(SELECT 0 AS min_val, 999 AS max_val FROM DUAL
UNION ALL
SELECT 1000, 2999 FROM DUAL),
q1 AS
(SELECT *
FROM my_table
PIVOT
(COUNT (*) FOR cond IN ('aa' AS aa, 'bb' AS bb)))
SELECT min_val,
max_val,
COUNT (aa) as val1,
SUM (aa * amount) as amount1,
COUNT (bb) as val2,
SUM (bb * amount) as amount2
FROM q1 JOIN value_groups ON amount BETWEEN min_val AND max_val
GROUP BY min_val, max_val
I've also converted your CASE
statements into a pivot. This will group matching sets of count/amount (i.e. if there are two 'aa' rows with an amount of 100, that will be returned as amount=100, count=2), which is why I'm multiplying the two to get the correct sum.
add a comment |
To do what you're attempting you need to manifest the min/max groups into a table-like structure. You're already most of the way there: the easy way to do this is to use the WITH
clause.
WITH value_groups AS
(SELECT 0 AS min_val, 999 AS max_val FROM DUAL
UNION ALL
SELECT 1000, 2999 FROM DUAL),
q1 AS
(SELECT *
FROM my_table
PIVOT
(COUNT (*) FOR cond IN ('aa' AS aa, 'bb' AS bb)))
SELECT min_val,
max_val,
COUNT (aa) as val1,
SUM (aa * amount) as amount1,
COUNT (bb) as val2,
SUM (bb * amount) as amount2
FROM q1 JOIN value_groups ON amount BETWEEN min_val AND max_val
GROUP BY min_val, max_val
I've also converted your CASE
statements into a pivot. This will group matching sets of count/amount (i.e. if there are two 'aa' rows with an amount of 100, that will be returned as amount=100, count=2), which is why I'm multiplying the two to get the correct sum.
To do what you're attempting you need to manifest the min/max groups into a table-like structure. You're already most of the way there: the easy way to do this is to use the WITH
clause.
WITH value_groups AS
(SELECT 0 AS min_val, 999 AS max_val FROM DUAL
UNION ALL
SELECT 1000, 2999 FROM DUAL),
q1 AS
(SELECT *
FROM my_table
PIVOT
(COUNT (*) FOR cond IN ('aa' AS aa, 'bb' AS bb)))
SELECT min_val,
max_val,
COUNT (aa) as val1,
SUM (aa * amount) as amount1,
COUNT (bb) as val2,
SUM (bb * amount) as amount2
FROM q1 JOIN value_groups ON amount BETWEEN min_val AND max_val
GROUP BY min_val, max_val
I've also converted your CASE
statements into a pivot. This will group matching sets of count/amount (i.e. if there are two 'aa' rows with an amount of 100, that will be returned as amount=100, count=2), which is why I'm multiplying the two to get the correct sum.
answered Nov 23 '18 at 14:30
AllanAllan
14.7k34255
14.7k34255
add a comment |
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.
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.
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%2f53446806%2fplsql-where-condition-outside-of-subquery%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
1
You could probably get some better answers, if you'd describe your real problem in more detail. I.e. what problem is the original query addressing? That way we may be able to give you better alternatives, than just blindly trying to follow your only direction (which may not necessarily be the the best, if possible at all).
– Hilarion
Nov 23 '18 at 12:39
it's about the same as the first query but with the (case when cond = 'aa' then 1 end) with more complicated conditions and with more than 20 case and even more union Further more the number of steps (between x an y) will change depending what is asked and my table is already the result of a with clause
– user1753180
Nov 23 '18 at 13:21