SQL COUNT - Output table with two COUNT columns with differing WHERE clauses - sql

I have the need to generate a report in Oracle APEX that is similar to the example below:
PROJECT OPEN_ISSUE_COUNT CLOSED_ISSUE_COUNT
W-1 3 1
X-2 1 2
Y-3 5 3
Z-4 2 1
Where OPEN_ISSUE_COUNT and CLOSED_ISSUE_COUNT are generated by a SQL COUNT statement. The table being queried looks like this:
ISSUE_# ISSUE_STATUS ASSOCIATED_PROJECT
1A OPEN W-1
1B OPEN W-1
1C OPEN W-1
2A CLOSED W-1
2B OPEN X-2
2C CLOSED X-2
3A CLOSED X-2
etc...
So in one query I need to count for OPEN_ISSUE_COUNT and CLOSED_ISSUE_COUNT where ISSUS_STATUS = 'OPEN' and ISSUS_STATUS = 'CLOSED' respectively and GROUP BY ASSOCIATED_PROJECT.
Does that make sense? Obviously I can easily do this for one of the two statuses, but have been unable to come up with any viable solution for what I am describing here. I have looked over some stuff here and elsewhere online and did not see something similar. Let me know what you guys think. Thanks!

Since count() only counts non-null values, this should work:
select associated_project as project,
count(case when issue_status='OPEN' then 1 else null end) as open_issue_count,
count(case when issue_status='CLOSED' then 1 else null end) as closed_issue_count
from table
group by associated_project;
Of course, this assumes that the only valid values for issue_status are 'OPEN' AND 'CLOSED'. If this isn't the case--and if you want those other statuses counted--then adjust the query accordingly.

Another way to do it is with the new PIVOT feature:
with issue_data as (
select associated_project as project, issue_status from issues
)
select project, open, closed
from issue_data
pivot ( count(*) for issue_status in ('OPEN' as open, 'CLOSED' as closed) )

select
sum(case when status = 'open' then 1 else 0 end) as open,
sum(case when status = 'closed' then 1 else 0 end) as closed
from table
where <other restrictions>

Related

Creating flag column

I would like to ask you for your help. I want to create a flag column, that will mark specific contract numbers whith 1, where the "CLOSED" column is empty in some rows.
I tried
case when CLOSED is null then 1 else 0 end as flag
group by CONTRACT_NUMBER
but it's not working. Thank you for your responses
example picture
I think you need analytic max() here:
demo
select t.*,
max(case when closed is null
then 1
else 0
end) over (partition by contract_number) as flag
from t

Using a case statement to show the count of two types of values in a column

SELECT
qt.name,
CASE
WHEN qr.isfinished = 0 THEN COUNT(qr.resultid)
END AS 'Attempted',
CASE
WHEN qr.isfinished = 1 THEN COUNT(qr.resultid)
END AS 'Completed'
Need it to show attempted and completed values on the same row
Name attempted Completed
--------------------------------
Algebra I 114 NULL
Algebra II 47 NULL
ASVAB 55 NULL
Algebra I NULL 69
Algebra II NULL 55
ASVAB NULL 84
Thank you for the help!
If isfinished is bit, you can't aggregate on it.
And the CASE goes inside the COUNT
SELECT qt.name,
count(Case when qr.isfinished = 0 THEN 1 END) as 'Attempted',
count(Case when qr.isfinished = 1 THEN 1 END) as 'Completed'
FROM
...
GROUP BY
qt.name
There are multiple ways you could do this, for example you could do this with joins, or you can use group by -- like so:
SELECT
qt.name,
SUM(CASE qr.isfinsihed WHEN 1 THEN 1 ELSE 0) AS 'Attempted',
SUM(CASE qr.isfinished WHEN 0 THEN 1 ELSE 0) AS 'Completed'
FROM -- what ever your from clause is, it goes here --
GROUP BY
qt.name
In order to have them on the same row, you will need to group by what they have in common. From what you have given in the question, I am assuming that is the qt.name.
Next, you can use the SUM aggregate to get each field count. All of the records that meet the criteria for each item count towards the sum, the others don't. You can also use count with 1's and Null's, I prefer using Sum because it can allow for weighted totals if I need them.

SQL select from the column and show specific output based on values in the column

I have a scenario where i need to show specific value in new column if I find any specific value( i.e Open, close,WIP then open) and if status =closed then show closed
Data :
ID SUBID Status
1 5 new
1 6 close
1 7 wip
2 22 closed
output i want to get
ID status
1 open
2 closed
You could think about this backwards, and use the else to catch all 'non-closed' rows.
select distinct
id,
case when status = 'closed' then 'closed' else 'open' end
from
yourTable
Scsimon's answer is 100% the best way to handle this based on your sample data.
Just want to add that if an id can have records with 'closed' and other records too (open, new, wip, etc.), use CASE WHEN EXISTS:
SELECT DISTINCT
ID,
CASE WHEN EXISTS (SELECT 1
FROM YourTable T2
WHERE T.ID = T2.ID
AND Status = 'closed')
THEN 'closed'
ELSE 'open'
END as Status
FROM YourTable T

SQL count on a field which is a code

I have a table
ANSWERS
qId
toggle_value
which records an HTML radio button value {Yes, N/A, No, Resolved}
Now I want to count and summarize how many yeses, nos, nas and resolved grouped by question Id.
For simplicity I started to build each individual query.
SELECT qId, count(*) as yes_qty FROM ANSWERS WHERE TOGGLE_VALUE='Yes' GROUP BY qId;
SELECT qId, count(*) as na_qty FROM ANSWERS WHERE TOGGLE_VALUE='NA' GROUP BY qId;
SELECT qId, count(*) as no_qty FROM ANSWERS WHERE TOGGLE_VALUE='No' GROUP BY qId;
SELECT qId, count(*) as resolved_qty FROM ANSWERS WHERE TOGGLE_VALUE='Resolved' GROUP BY qId;
But I really want it in one query so I can iterate over the list and display something like this ( aggregating 14 Checklists with 3 questions)
Q Yes No NA Resolved
1 4 10 0 10
2 14 0 0 0
3 7 0 7 0
I don't actually use strings for the toggle value but numbers 1=yes, 2=NA, etc... and was wondering if a better table design would have been
ANSWERS
qId
yes_value
no_value
na_value
resolved_value
I'd have to refactor a lot of other things if I changed the table deisgn so I was hoping to get a single query working.
SELECT qId,
SUM(CASE WHEN TOGGLE_VALUE='Yes' THEN 1 ELSE 0 END) AS YesQty,
SUM(CASE WHEN TOGGLE_VALUE='No' THEN 1 ELSE 0 END) AS NoQty,
SUM(CASE WHEN TOGGLE_VALUE='NA' THEN 1 ELSE 0 END) AS NAQty,
SUM(CASE WHEN TOGGLE_VALUE='Resolved' THEN 1 ELSE 0 END) AS ResolvedQty
FROM ANSWERS
GROUP BY qId
I like your table design. I would personally solve this with a SUM and GROUP BY and using CASE clauses to create new columns.

SQL Count with multiple conditions then join

Quick one,
I have a table, with the following structure
id lid taken
1 1 0
1 1 0
1 1 1
1 1 1
1 2 1
Pretty simply so far right?
I need to query the taken/available from the lid of 1, which should return
taken available
2 2
I know I can simply do two counts and join them, but is there a more proficient way of doing this rather than two separate queries?
I was looking at the following type of format, but I can not for the life of me get it executed in SQL...
SELECT
COUNT(case taken=1) AS taken,
COUNT(case taken=0) AS available FROM table
WHERE
lid=1
Thank you SO much.
You can do this:
SELECT taken, COUNT(*) AS count
FROM table
WHERE lid = 1
GROUP BY taken
This will return two rows:
taken count
0 2
1 2
Each count corresponds to how many times that particular taken value was seen.
Your query is correct just needs juggling a bit:
SELECT
SUM(case taken WHEN 1 THEN 1 ELSE 0 END) AS taken,
SUM(case taken WHEN 1 THEN 0 ELSE 1 END) AS available FROM table
WHERE
lid=1
Alternatively you could do:
SELECT
SUM(taken) AS taken,
COUNT(id) - SUM(taken) AS available
FROM table
WHERE
lid=1
SELECT
SUM(case WHEN taken=1 THEN 1 ELSE 0 END) AS taken,
SUM(case WHEN taken=0 THEN 1 ELSE 0 END) AS available
FROM table
WHERE lid=1
Weird application of CTE's:
WITH lid AS (
SELECT DISTINCT lid FROM taken
)
, tak AS (
SELECT lid,taken , COUNT(*) AS cnt
FROM taken t0
GROUP BY lid,taken
)
SELECT l.lid
, COALESCE(a0.cnt, 0) AS available
, COALESCE(a1.cnt, 0) AS taken
FROM lid l
LEFT JOIN tak a0 ON a0.lid=l.lid AND a0.taken = 0
LEFT JOIN tak a1 ON a1.lid=l.lid AND a1.taken = 1
WHERE l.lid=1
;