Count with Case Select in Oracle - oracle

I have the following query:
SELECT t.range,
Count(*)
FROM (
SELECT CASE
WHEN creditscore BETWEEN 300
AND 499
THEN '[300, 499]'
WHEN creditscore BETWEEN 500
AND 699
THEN '[500, 699]'
WHEN creditscore BETWEEN 700
AND 850
THEN '[700, 850]'
END AS range
FROM customer
) T
GROUP BY t.range;
Which gives me the following :
CS range COUNT(*)
---------- ----------
[700, 850] 7
[500, 699] 13
I want the following output:
CS range COUNT(*)
---------- ----------
[300, 499] 0
[500, 699] 13
[700, 850] 7
Can anyone help me out?
UPDATE
I executed the code the Justin provided. It gives me the following:
DESCRIPTIO COUNT(*)
---------- ----------
[300, 499] 1
[700, 850] 7
[500, 699] 13
SQL> SELECT COUNT(*) FROM customer where creditscore BETWEEN 300 AND 499;
COUNT(*)
----------
0

One option would be to do something like
WITH ranges AS (
SELECT '[300, 499]' description, 300 min_val, 499 max_val FROM dual
UNION ALL
SELECT '[500, 699]' description, 500 min_val, 699 max_val FROM dual
UNION ALL
SELECT '[700, 850]' description, 700 min_val, 850 max_val FROM dual
)
SELECT r.description, count(creditscore)
FROM ranges r
LEFT OUTER JOIN customer c
ON (c.creditscore BETWEEN r.min_val AND r.max_val)
GROUP BY r.description
Normally, you'd want to set up a permanent table with your ranges in case someone wants to add or modify them in the future. But you can hard-code the ranges in your query like I do here.

You can use unpivot in this case.
Your answer-
Select * From
(
Select Sum(Col1) "[300, 499]", Sum(Col2) "[500, 699]", Sum(Col3) "[700, 850]"
From (
Select Case
When Creditscore Between 300
And 499
Then 1 Else 0 End As Col1,
Case When Creditscore Between 500
And 699
Then 1 Else 0 End Col2,
Case When Creditscore Between 700
And 850
Then 1 Else 0 End Col3
From Customer
)
)
Unpivot
(
"Count"
For
"Description" In ("[300, 499]", "[500, 699]", "[700, 850]")
);
Result -
Description Count
[300, 499] 0
[500, 699] 4
[700, 850] 3

Related

How to sum total amount without grouping even have duplicated number?

table_a table_b
desc amount ID vcref ID
banana 2.00 101 VC10001 101
apple 3.00 101 VC10001 101
orange 5.00 101 VC10003 101
select sum(a.amount),b.vcref from table_a a,table_b b where a.ID=b.ID group by b.vcref;
result
20.0 VC10001
10.0 VC10003
-------------------------------------------
May I know it is possible to show result like this ?
result
10.0 VC10001
10.0 VC10001
10.0 VC10003
Anyone help is much appreciated.
One option is to use a correlated subquery:
Sample data:
SQL> with
2 table_a (c_desc, amount, id) as
3 (select 'banana', 2, 101 from dual union all
4 select 'apple' , 3, 101 from dual union all
5 select 'orange', 5, 101 from dual
6 ),
7 table_b (vcref, id) as
8 (select 'vc1001', 101 from dual union all
9 select 'vc1001', 101 from dual union all
10 select 'vc1003', 101 from dual
11 )
Query:
12 select b.vcref,
13 (select sum(a.amount) from table_a a where a.id = b.id) total
14 from table_b b;
VCREF TOTAL
------ ----------
vc1001 10
vc1001 10
vc1003 10
SQL>
Select the sum as an inner query:
select
(select sum(amount) from table_a) as result,
vcref
from table_b

Oracle query where one column with multiple values must be different

I'm having trouble trying to come up with a query that retrieves COLUMN_A where:
COLUMN_C is having count > 1
And COLUMN_B's values are different.
Table contents
COLUMN_A COLUMN_B COLUMN_C
-------------------------------- ---------------- ---------
000111222 AAAAAAAAA 100
000111222 BBBBBBBBB 100
000111222 CCCCCCCCC 300
000111222 CCCCCCCCC 300
000888999 DDDDDDDDD 300
000888999 DDDDDDDDD 300
777666555 EEEEEEEEE 100
777666555 FFFFFFFFF 100
234567890 GGGGGGGGG 100
234567890 GGGGGGGGG 100
444333111 HHHHHHHHH 100
Expected result
COLUMN_A COLUMN_B COLUMN_C
-------------------------------- ---------------- ---------
000111222 AAAAAAAAA 100
000111222 BBBBBBBBB 100
777666555 EEEEEEEEE 100
777666555 FFFFFFFFF 100
This is where I'm stuck at:
select COLUMN_A, count(*) from SOME_TABLE where COLUMN_C = '100' group by COLUMN having count(*) > '1';
But this query retrieves:
COLUMN_A COLUMN_B COLUMN_C
-------------------------------- ---------------- ---------
000111222 AAAAAAAAA 100
000111222 BBBBBBBBB 100
777666555 EEEEEEEEE 100
777666555 FFFFFFFFF 100
234567890 GGGGGGGGG 100
234567890 GGGGGGGGG 100
I strongly suspect the query lacks a distinct or a count somewhere but, for the life of me, nothing comes to mind.
Any info would be greatly appreciated.
We can try to use two count window functions in the subquery for your grouping logic.
SELECT t1.COLUMN_A ,t1.COLUMN_B ,t1.COLUMN_C
FROM (
select t1.*,
count(*) OVER(PARTITION BY COLUMN_A,COLUMN_B) cnt1,
COUNT(*) OVER(PARTITION BY COLUMN_A,COLUMN_C) cnt2
from SOME_TABLE t1
) t1
WHERE cnt1 = 1 AND cnt2 > 1
sqlfiddle
You can use:
SELECT column_a, column_b, column_c
FROM (
SELECT t.*,
COUNT(column_b) OVER (PARTITION BY column_a, column_c) AS cnt_all,
COUNT(DISTINCT column_b) OVER (PARTITION BY column_a, column_c)
AS cnt_dst
FROM table_name t
)
WHERE cnt_all = cnt_dst
AND cnt_dst > 1
Which, for the sample data:
CREATE TABLE table_name (COLUMN_A, COLUMN_B, COLUMN_C) AS
SELECT '000111222', 'AAAAAAAAA', 100 FROM DUAL UNION ALL
SELECT '000111222', 'BBBBBBBBB', 100 FROM DUAL UNION ALL
SELECT '000111222', 'CCCCCCCCC', 300 FROM DUAL UNION ALL
SELECT '000111222', 'CCCCCCCCC', 300 FROM DUAL UNION ALL
SELECT '000888999', 'DDDDDDDDD', 300 FROM DUAL UNION ALL
SELECT '000888999', 'DDDDDDDDD', 300 FROM DUAL UNION ALL
SELECT '777666555', 'EEEEEEEEE', 100 FROM DUAL UNION ALL
SELECT '777666555', 'FFFFFFFFF', 100 FROM DUAL UNION ALL
SELECT '234567890', 'GGGGGGGGG', 100 FROM DUAL UNION ALL
SELECT '234567890', 'GGGGGGGGG', 100 FROM DUAL UNION ALL
SELECT '444333111', 'HHHHHHHHH', 100 FROM DUAL;
Outputs:
COLUMN_A
COLUMN_B
COLUMN_C
000111222
AAAAAAAAA
100
000111222
BBBBBBBBB
100
777666555
EEEEEEEEE
100
777666555
FFFFFFFFF
100
db<>fiddle here

Oracle Subquery while using count and max with join

Table COMPUTER:
Table SUPPLIER:
how to display the building location that has the most computers?
i Have been trying several ways include subquery, joins, max, count but all not working and error keeps happending
The result i pursueing is
SUPPID SNAME SADDRESS MAKE COUNT(*)
125 Apple Sdn.Bhd 18 Jalan Duta Apple 3
For example (where sample data is in lines #1 - 12; query you might be interested in begins at line #13):
SQL> with
2 -- sample data
3 computer (compid, make, suppid, locid) as
4 (select 13323, 'IBM' , 124, 333 from dual union all
5 select 13324, 'Apple', 125, 444 from dual union all
6 select 13325, 'Apple', 125, 444 from dual union all
7 select 13326, 'Apple', 125, 444 from dual
8 ),
9 supplier (suppid, sname, saddress) as
10 (select 124, 'IBM Sdn.Bhd' , '15 Jalan Duta' from dual union all
11 select 125, 'Apple Sdn.Bhd', '18 Jalan Duta' from dual
12 ),
13 comp_loc as
14 -- number of computers per location; RNK = 1 shows location with most computers
15 (select locid,
16 rank() over (order by count(*) desc) rnk,
17 count(*) cnt
18 from computer
19 group by locid
20 )
21 select distinct s.suppid, s.sname, s.saddress, c.make, l.cnt
22 from supplier s join computer c on c.suppid = s.suppid
23 join comp_loc l on l.locid = c.locid
24 where l.rnk = 1;
SUPPID SNAME SADDRESS MAKE CNT
---------- ------------- ------------- ----- ----------
125 Apple Sdn.Bhd 18 Jalan Duta Apple 3
SQL>
On Oracle 12 and newer
select s.suppid, s.sname, s.saddress, c.make, count(1)
from COMPUTER c
join SUPPLIER s
on c.suppid = s.suppid
group by s.suppid, s.sname, s.saddress, c.make
order by count(1) desc
fetch first 1 row only <-- this line will fetch you the top 1 line only
You might also use "fetch first 1 row with ties" to output all the top manufacturers if there are many of them having same "count". E.g If IBM and Appl were having same amount of lines
On Oracle version before 12 do the following:
select *
from (select s.suppid, s.sname, s.saddress, c.make, count(1)
from comps c
join suppls s
on c.suppid = s.suppid
group by s.suppid, s.sname, s.saddress, c.make
order by count(1) desc)
where rownum = 1; <-- this line will get you the top 1 manufacturer only
PS. version of the oracle database can be obtained for example using:
select version from v$instance;

How to write 'select query' for finding difference between debit of one account and credit of another account using one table only?

Sql statements:
SELECT debit,credit FROM transactionentries where glaccountid = 15374;
SELECT debit,credit FROM transactionentries where glaccountid = 15376;
Hint: the debit for this glaccountid, 15374 must be equal to the credit for other glaccountid, 15376 and vice verse.
What i am trying to get is to return transaction entries where the debit of one account is not equal to the credit of the other account.
Any help ?
Thanks in advance.
My attempt:
SELECT debit,credit FROM transactionentries
where glaccountid = 15374
and debit not in (
SELECT credit FROM transactionentries where glaccountid = 15376
);
Query above returns no rows and i expect to return transaction entries where the debit of one account is not equal to the credit of the other account.
Self cross join might help.
SQL> with transactionentries (glaccountid, debit, credit) as
2 (select 15374, 100, 200 from dual union all -- different: 100 <> 101 and ...
3 select 15376, 201, 101 from dual union all -- ... 200 <> 201
4 --
5 select 1, 1000, 2000 from dual union all -- same: 1000 = 1000 and ...
6 select 2, 2000, 1000 from dual ... 2000 = 2000
7 )
8 select a.glaccountid, a.debit a_debit, b.credit b_credit,
9 b.glaccountid, b.debit b_debit, a.credit a_credit
10 from transactionentries a cross join transactionentries b
11 where a.glaccountid = 15374
12 and b.glaccountid = 15376
13 and ( a.debit <> b.credit
14 or b.debit <> a.credit
15 );
GLACCOUNTID A_DEBIT B_CREDIT GLACCOUNTID B_DEBIT A_CREDIT
----------- ---------- ---------- ----------- ---------- ----------
15374 100 101 15376 201 200
SQL>
If values in lines #11 and #12 are modified to 1000 and 2000, query won't return anything because those values match.
Though, that's impractical approach as you must know a and b pairs whose debits and credits should match. If there's something you could use to automate it, use it.
select * from transactionentries s
where not exists ( select 1 from transactionentries p
where p.debit=s.credit
and s.debit=p.credit);

how to get following output in oracle using query?

I've following data like
ano asal
------------------
1 100
1 150
1 190
2 200
2 240
3 300
3 350
4 400
4 400
4 400
i want ans like max sal from 1 ,from 2,3 and 4
o/p like
ano asal
---------------
1 190
2 240
3 390
4 400
4 400
4 400
You want to return the max value of asal for each ano group, but you want to retain the duplicates in the original table if they exist. This means you can't just do a simple GROUP BY. But you can use a GROUP BY query to identify the max values and then retain those records via an INNER JOIN. Try this query:
SELECT t1.ano, t1.asal
FROM yourTable t1
INNER JOIN
(
SELECT ano, MAX(asal) AS asal
FROM yourTable
GROUP BY ano
) t2
ON t1.ano = t2.ano AND t1.asal = t2.asal
You can use an union the firt select with group by
select ano, max(asal)
from my_table
where ano != 4
group by ano
union all
select ano, asal
from my_table
where ano = 4
order by ano
SELECT
ano, asal
FROM (
SELECT
data.*,
MAX(asal) OVER (PARTITION BY ano) max
FROM
data)
WHERE
asal = max

Resources