I have a column called "status" in a sql table called "latest" which contains five different values new,deployed,resolved,assigned and closed as shown below
Status
--------------
NEW
NEW
DEPLOYED
NEW
RESOLVED
ASSIGNED
ASSIGNED
RESOLVED
ASSIGNED
NEW
NEW
RESOLVED
CLOSED
ASSIGNED
I want to write a query in which i can count the number of times each of these words occur in the column "status". Currently I'm using count function in 5 different queries like this.
1)select count(status) from latest where status="NEW";
2)select count(status) from latest where status="DEPLOYED";
3)select count(status) from latest where status="RESOLVED";
4)select count(status) from latest where status="ASSIGNED";
5)select count(status) from latest where status="CLOSED";
Is there a way i could combine all these queries into single query without using joins or union to get 5 different count values??
QUERY 1:
SELECT STATUS, COUNT(1) FROM LATEST
GROUP BY STATUS
ORDER BY STATUS;
Your Output would be:
STATUS COUNT
ASSIGNED 4
CLOSED 1
DEPLOYED 1
NEW 5
RESOLVED 3
To get the output in single row with 5 columns you can use:
QUERY 2:
SELECT COUNT(CASE WHEN STATUS='ASSIGNED' THEN 1 END) ASSIGNED_COUNT,
COUNT(CASE WHEN STATUS='CLOSED' THEN 1 END) CLOSED_COUNT,
COUNT(CASE WHEN STATUS='DEPLOYED' THEN 1 END) DEPLOYED_COUNT,
COUNT(CASE WHEN STATUS='NEW' THEN 1 END) NEW_COUNT,
COUNT(CASE WHEN STATUS='RESOLVED' THEN 1 END) RESOLVED_COUNT
FROM LATEST
Your Output would be:
ASSIGNED_COUNT | CLOSED_COUNT | DEPLOYED_COUNT | NEW_COUNT | RESOLVED_COUNT
4 | 1 | 1 | 5 | 3
EXPLANATION:
Query 1 can be used where there can be any number of dynamic status. For example, even if there is a status named DEFERRED, it would automatically be included without query change. But, if there is say, no record with status as "NEW", then no data would be returned.
Query 2 can be used to return all the data in a single row. If a new status is to be included, then the query must be modified. If there are no records for a status, then 0 would be returned. IDEAL FOR DASHBOARD kind of usage.
Try this cool one
Select *
from
(
Select Status,COUNT(*) 'Count'
from LATEST
group by Status with rollup
) t
where t.Count is not null
Try this:
SELECT l.status, COUNT(1)
FROM latest l
GROUP BY l.status;
OR
SELECT SUM(l.status = 'NEW') AS NEW_STATUS,
SUM(l.status = 'DEPLOYED') AS DEPLOYED_STATUS,
SUM(l.status = 'RESOLVED') AS RESOLVED_STATUS,
SUM(l.status = 'ASSIGNED') AS ASSIGNED_STATUS,
SUM(l.status = 'CLOSED') AS CLOSED_STATUS
FROM latest l;
UPDATE
Use SELECT...INTO statement to achieve this, check below query
SELECT SUM(l.status = 'NEW') AS NEW_STATUS,
SUM(l.status = 'DEPLOYED') AS DEPLOYED_STATUS,
SUM(l.status = 'RESOLVED') AS RESOLVED_STATUS,
SUM(l.status = 'ASSIGNED') AS ASSIGNED_STATUS,
SUM(l.status = 'CLOSED') AS CLOSED_STATUS
INTO NEW_STATUS, DEPLOYED_STATUS, RESOLVED_STATUS,
ASSIGNED_STATUS, CLOSED_STATUS
FROM latest l;
Try This...
1.>
Select Count() as Count,Status from latest where (status='NEW' Or status='DEPLOYED' or status='RESOLVED' or status='ASSIGNED' Or status='CLOSED') group by Status;*
OR
2.>
select count(status) from latest where (status='NEW' Or status='DEPLOYED' or status='RESOLVED' or status='ASSIGNED' Or status='CLOSED');
Related
Assume that have a scenario like in request table with same request Id I may have multiple records with different statuses
status like Draft, InProgress, Approved, Completed . we need to fetch single highest status record. Here preferred order is Completed -> Approved -> InProgress -> Draft.
if have three records like one is with InProgress, one with Approved and another one is with Completed, then among these three in need fetch only one record which have highest status Completed.
if have two records like one is with InProgress and another one is with Draft, then among these two in need fetch only one record which have highest status InProgress.
Could any one please suggest me on this ?
Use the ROW_NUMBER analytic function to order the rows based on a CASE expression that converts your string values to priorities:
SELECT *
FROM (
SELECT t.*,
ROW_NUMBER() OVER (
PARTITION BY request_id
ORDER BY CASE status
WHEN 'Completed' THEN 1
WHEN 'Approved' THEN 2
WHEN 'InProgress' THEN 3
WHEN 'Draft' THEN 4
ELSE 5
END
) as rn
FROM table_name t
)
WHERE rn = 1;
Its a bit of an heinous solution (tested on postgresql) - but you can convert your textual status into a number with a CASE statement and then use that plus a subquery to get the highest status:
SELECT rt.*
FROM
(SELECT
id,
MAX(CASE
WHEN status = 'Draft' THEN 0
WHEN status = 'InProgress' THEN 10
WHEN status = 'Approved' THEN 20
WHEN status = 'Completed' THEN 30
END) AS msid
FROM
request_table
GROUP BY
id) max_per_id
INNER JOIN
request_table rt ON max_per_id.id = rt.id
AND max_per_id.msid = CASE WHEN rt.status='Draft' THEN 0 WHEN rt.status='InProgress' then 10 WHEN rt.status='Approved' THEN 20 WHEN rt.status='Completed' then 30 END
The subquery
SELECT
id,
MAX(CASE
WHEN status = 'Draft' THEN 0
WHEN status = 'InProgress' THEN 10
WHEN status = 'Approved' THEN 20
WHEN status = 'Completed' THEN 30
END) AS msid
FROM
request_table
GROUP BY
id) max_per_id
provides the highest numeric status for each id. That then gets joined on the id and the numeric version of the status with the original table
I have a table with following rows :
SectionId
SectionStatus
1
Assigned
1
Approved
2
Assigned
2
Assigned
3
Assigned
Now I want to fetch the SectionId where al SectionStatus belong to that SectionId are not Approved.
Result expected for above table : 1,2,3
Another Example :
SectionId
SectionStatus
1
Approved
1
Approved
2
Assigned
2
Assigned
3
Assigned
Result expected for above table : 2,3
This looks like aggregation with a conditional count in the HAVING clause.
SELECT t.SectionId
FROM yourtable t
GROUP BY t.SectionId
HAVING COUNT(CASE WHEN t.SectionStatus = 'Approved' THEN 1 END) = 0;
db<>fiddle
One way to get that is by cross-applying the record and check whether that is 'Approved' or not.
Try the following:
select distinct SectionId from yourtable tab
cross apply (select 'Approved' Stat)t
where t.Stat <> tab.SectionStatus
Please see the db<>fiddle here.
I am trying to write a query from a table A which has 2 columns :
ID , STATUS
The Status can be PROCESSING, NOTPROCESSED, FAILED, SUCCESS
When a record is successfully processed, a new record is created in the DB with STATUS as PROCESSED and the ID is the same as the previous NOTPROCESSED record.
The Sample Records in DB would like :
1 NOTPROCESSED
2 PROCESSED
1 PROCESSED
3 NOTPROCESSED
4 NOTPROCESSED
2 PROCESSED
3 NOTPROCESSED
4 NOTPROCESSED
The records can appear as duplicate for NOTPROCESSED.
I have to query the records which are NOTPROCESSED i.e
3 NOTPROCESSED
4 NOTPROCESSED
Its getting quite confusing to write the query.
Can anyone help with the logic.
you may use not exists to get this output.
select distinct a.id,a.status
from table a
where a.status='NOTPROCESSED'
and not exists (select null
from table b
where b.id=a.id
and b.status='PROCESSED')
Group by the ids and take only those groups having no record of status PROCESSED
select id
from your_table
group by id
having sum(case when status = 'PROCESSED' then 1 else 0 end) = 0
or get only the ones with only one kind of status
having count(distinct status) = 1
or use alphabetically the highest status
having max(status) = 'NOTPROCESSED'
Here are a couple of options:
select distinct id from A where id not in (
select id from A where status = 'PROCESSED'
);
select distinct id from A natural left join (
select id from A where status = 'PROCESSED'
) as B where B.id is null;
You can use analytical function as follows:
select * from
(select t.*, count(case when status = 'PROCESSED' then 1 end)
over (partition by ID) as cnt
from your_table t) t
where status = 'NOTPROCESSED' and cnt = 0
My goal is something like following table:
Key | Count since date X | Count total
1 | 4 | 28
With two simple selects I could gain this values: (the key of the table consists of 3 columns [t$ncmp, t$trav, t$seqn])
1. SELECT COUNT(*) FROM db.table WHERE t$date >= sysdate-2 GROUP BY t$ncmp, t$trav, t$seqn
2. SELECT COUNT(*) FROM db.table GROUP BY t$ncmp, t$trav, t$seqn
How can I join these statements?
What I tried:
SELECT n.t$trav, COUNT(n.t$trav), m.total FROM db.table n
LEFT JOIN (SELECT t$ncmp, t$trav, t$seqn, COUNT(*) as total FROM db.table
GROUP BY t$ncmp, t$trav, t$seqn) m
ON (n.t$ncmp = m.t$ncmp AND n.t$trav = m.t$trav AND n.t$seqn = m.t$seqn)
WHERE n.t$date >= sysdate-2
GROUP BY n.t$ncmp, n.t$trav, n.t$seqn
I tried different variantes, but always got errors like 'group by is missing' or 'unknown qualifier'.
Now this at least executes, but total is always 2.
T$TRAV COUNT(N.T$TRAV) TOTAL
4 2 2
29 3 2
51 1 2
62 2 2
16 1 2
....
If it matter, I will run this as an OPENQUERY from MSSQLSERVER to Oracle-DB.
I'd try
GROUP BY n.t$trav, m.total
You typically GROUP BY the same columns as you SELECT - except those who are arguments to set functions.
My goal is something like following table:
If so, you seem to want conditional aggregation:
select key, count(*) as total,
sum(case when datecol >= date 'xxxx-xx-xx' then 1 else 0 end) as total_since_x
from t
group by key;
I'm not sure how this relates to your sample queries. I simply don't see the relationship between that code and your question.
I need a SQL Server and Oracle compatible query to get the following result
Table:
PRIMARY IDN SECONDARY_IDN STATUS
1 47 Pending
2 47 Completed
3 47 Error
4 57 Pending
5 59 Completed
6 60 Pending
7 60 Completed
My input would be either Pending, Completed, or Error.
I need to list out all the secondary IDN with just 1 status and that is the input status.
For example my input is Pending: it should show up 57 ONLY. Others might have Pending but it also has completed and error records .
Can you please help me ?
SELECT SECONDARY_IDN
FROM tableName
GROUP BY SECONDARY_IDN
HAVING SUM(CASE WHEN Status = 'Pending' THEN 1 ELSE 0 END) = COUNT(*)
SQLFiddle Demo
You need groups that have only one status. For that, you want to use aggregation:
select secondary_idn
from t
group by secondary_idn
having max(status) = min(status) and -- all the statuses are the same
max(status) = 'Pending' -- and the status is Pending
SELECT *
FROM tableName tn
WHERE tn.Status = 'Pending'
AND NOT EXISTS ( SELECT *
FROM tableName nx
WHERE nx.SECONDARY_IDN = tn.SECONDARY_IDN
AND nx.Status <> 'Pending'
);
The outer query has no group by, so all columns are available to it (the dreaded select * is there to illustrate this fact)
The exists needs to detect only one unwanted record to yield true, solutions with aggregates (min, max, count) may have to scan (and aggregate) the whole group to establish the desirability of the record.
select status
, secondary_idn
, count(*) records
from theTable
where whatever
group by status, secondary_idn
having count(*) = 1