If I have a table with a status field and I want to know how many records of each status I can do a simple group by. And how about if I want to know the count for 2 records and the count for all the others.
In other words I want this:
Status Count
-------- -----
Success X
Running Y
Failure Z
but Failure is not Failure on the table, it contains the actual error message, so I want everything that's different that Success and Running
select case when Status <> 'Success'
and Status <> 'Running'
then 'Failure'
else Status
end Status,
count (*) [Count]
from atable
group by case when Status <> 'Success'
and Status <> 'Running'
then 'Failure'
else Status
end
Click here to view the demo in SQL Fiddle.
Script:
CREATE TABLE errormsgs
(
id INT NOT NULL IDENTITY
, statusmsg VARCHAR(30) NOT NULL
);
INSERT INTO errormsgs (statusmsg) VALUES
('Success'),
('This is error message 1.'),
('Running'),
('This is error message 2.'),
('This is error message 3.'),
('Success'),
('Success'),
('This is error message 4.'),
('Running'),
('failure, may be'),
('failure, absolutely.');
;WITH statuses AS
(
SELECT CASE
WHEN statusmsg NOT IN ('Success', 'Running') THEN 'Failure'
ELSE statusmsg
END status
FROM errormsgs
)
SELECT status
, COUNT(status) AS status_count
FROM statuses
GROUP BY status;
Output:
STATUS STATUS_COUNT
-------- ------------
Failure 6
Running 2
Success 3
SELECT DISTINCT CASE
WHEN [status]='s' OR [STATUS]='r' THEN [status]
ELSE 'OTHER'
END AS STATUS
,COUNT(1) OVER(
PARTITION BY CASE
WHEN [status]='s'
OR [STATUS]='r' THEN [status] ELSE 'aaa' END
) AS 'count'
FROM tbl2
Related
customer_id
transaction success
1
Failed
2
Complete
1
Failed
1
Complete
3
Failed
2
Failed
3
Complete
3
Failed
3
Failed
3
Complete
Essentially I want to write a statement to identify if the customer has had a completed transaction after having had a failed transaction sometime before. So in this example, customer 1 and customer 2 would be satisfy this. Assume that there is an added timestamp column next to transaction success.
The resulting table should look like this:
customer_id
returning_success
1
True
2
False
3
True
Assuming that is not important if the Complete was after or prior to the Cancellation, you can LEFT JOIN the table with a subquery that only takes the completes. If the result is NULL, then is not have a complete state. Otherwise is true.
As you don't provide your DBMS (Please read: Why should I "tag my RDBMS"?) we take in consideration IFNULL but this can change in other DBMS: https://www.w3schools.com/sql/sql_isnull.asp
SELECT
yt.customer_id,
IFNULL(completes.customer_id,'false','true') as returning_success
FROM
yourtable yt
LEFT JOIN
(
SELECT
customer_id
FROM
yourTable
WHERE transaction_success = 'Complete') completes
ON completes.customer_id = yt.customer_id
If you just need customers that had had both succesfull and faild transactions, you should implement this:
select customer_id, case when sum(case
when transaction='Faild'
then 1
else 0 end)>0
and
sum(case
when transaction='Complete'
then 1
else 0 end)>0
then 'True'
else 'False' end
returning_success
from table_
group by customer_id
If you actually do have some timestamp column:
select nvl(c.customer_id, f.customer_id) customer_id
, case when last_complete_time is null
or first_fail_time is null
or first_fail_time>last_complete_time
then 'False'
else 'True' end
returning_success
from (
select customer_id, max(time_) last_complete_time
from table_
group by customer_id
where transaction='Complete'
) c
full join (
select customer_id, min(time_) first_fail_time
from table_
group by customer_id
where transaction='Fail'
) f on c.customer_id=f.customer_id
You also can use this query to filter all True cases and then just union or join the rest:
select f.customer_id, 'True'
from (
select customer_id, max(time_) last_complete_time
from table_
group by customer_id
where transaction='Complete'
) c
join (
select customer_id, min(time_) first_fail_time
from table_
group by customer_id
where transaction='Fail'
) f on c.customer_id=f.customer_id
where first_fail_time<last_complete_time
There is a status column in my table with int values. How can I assign a value to the int or do I have to create a new column in the table?
I have tried to ALTER table but what is the best method?
select status from table1;
If I run the above query we get -
id status
1 1
2 2
3 1
4 5
I want to get output -
id status
1 Accepted
2 Completed
3 Accepted
4 Declined
USE case expression, postgres
select status,
case
when status=1 then 'Accepted'
when status=2 then 'Completed'
when status=3 then 'Accepted'
when sttaus=4 then 'Declined'
end mystatus
from table1;
You can use case, refer to this SO Question
PostgreSQL CASE ... END with multiple conditions. The query will look something like this:
SELECT
id,
CASE
WHEN (status = 1) THEN 'Accepted'
WHEN status=2 then 'Completed'
WHEN status=3 then 'Accepted'
WHEN sttaus=4 then 'Declined'
END AS status
FROM table1 ;
The correct case expression would be:
select id,
(case status
when 1 then 'Accepted'
when 2 then 'Completed'
when 5 then 'Declined'
end) as status
from table1;
You can also do this with a join to a derived table:
select t1.id, v.status
from table1 t1 left join
(value (1, 'Accepted'), (2, 'Completed'), (5, 'Declined')
) v(status_int, status)
on t1.status = v.status_int;
I mention this because you should probably have a reference table for the status values. In this case, the reference table is created on the fly in the query. But it should probably be a real table in the database.
My current query is:
select rulename,status, count(*)
from triggered_rule_info
group by status, rulename
And the result is:
rulename status count
eorule1 ack 1
eorule1 open 1
eorule1 close 7
eorule2 open 1
eorule2 ack 1
But I want the result to be:
rulename ack open close
eorule1 1 1 7
eorule2 1 1
How can I achieve this? My postgresql version is 9.4.
For that you can use the filter clause:
select rulename
count(*) filter (where status = 'ack') as ack,
count(*) filter (where status = 'open') as open,
count(*) filter (where status = 'close') as closed
from triggered_rule_info
group by rulename
order by rulename;
You can make use of CASE - WHEN and GROUP BY clauses to get the desired result. You may require to add more CASE statements if status has more other values.
Example:
SELECT rulename
, SUM( CASE status WHEN 'ack' THEN 1 ELSE 0 END ) AS "ack"
, SUM( CASE status WHEN 'open' THEN 1 ELSE 0 END ) AS "open"
, SUM( CASE status WHEN 'close' THEN 1 ELSE 0 END ) AS "close"
FROM triggered_rule_info
GROUP BY rulename
ORDER BY rulename
I have these columns
Id Status
----------
1 pass
1 fail
2 pass
3 pass
How do I select all that only have a status of pass but if the Id has at least one fail it will not be selected as well.
If same id can have multiple passes
SELECT id
from table
WHERE status = 'pass'
and id NOT IN (SELECT id FROM table WHERE status = 'fail')
You need to use GROUP BY & HAVING clause
SELECT Id
FROM yourtable
GROUP BY Id
HAVING Sum(case when status ='pass' then 1 else 0 end) = count(status)
HAVING clause can be changed to
HAVING Count(case when status ='pass' then 1 end) = count(status)
I just hate chatty case statement, so
SELECT Id
FROM table1
GROUP BY Id
HAVING COUNT(DISTINCT [Status]) = 1 AND MIN([Status]) = 'pass'
or
SELECT Id
FROM table1
GROUP BY Id
HAVING COUNT(NULLIF([Status], 'fail')) = 1 AND COUNT(NULLIF([Status], 'pass')) = 0
The second query only works when status has two values 'pass' and 'fail'.
If I have a table with a schema like this
table(Category, SubCategory1, SubCategory2, Status)
I would like to group by Category, SubCategory1 and aggregate the Status such that
if not all Status values over the group have a certain value Status will be 0 otherwise 1.
So my result set will look like
(Category, SubCategory1, Status)
I don't want to write a function. I would like to do it inside the query.
Assuming that status is a numeric data type, use:
SELECT t.category,
t.subcategory1,
CASE WHEN MIN(t.status) = MAX(t.status) THEN 1 ELSE 0 END AS status
FROM dbo.TABLE_1 t
GROUP BY t.category, t.subcategory1
You can test that both the minimum and maximum status for each group are equal to your desired value:
SELECT
category,
subcategory1,
CASE WHEN MIN(status) = 42 AND MAX(status) = 42 THEN 1 ELSE 0 END AS Status
FROM table1
GROUP BY category, subcategory1
Let's say you want to find groups that have all status values under 100
SELECT category, subcategory1,
CASE WHEN MAX(status) < 100 THEN 0 ELSE 1 END AS Status
FROM table1
GROUP BY category, subcategory1
All groups with status under 100 will have Status set to 0, and all groups with at least one status >= 100 will be set to 1.
I think that's what you're asking for, but if not let me know.
I would like to group by Category,
SubCategory1 and aggregate the Status
such that if not all Status values
over the group have a certain value
Status will be 0 otherwise 1.
I'm interpreting this as "If there exists a Status value in a given group not equal to a given parameter, the returned Status will be 0 otherwise 1".
Select T.Category, T.SubCategory1
, Case
When Exists(
Select 1
From Table As T2
Where T2.Category = T.Category
And T2.SubCategory1 = T.SubCategory1
And T2.Status <> #Param
) Then 0
Else 1
End As Status
From Table As T
Group By t.Category, T.SubCategory1
Something like that :
select
Category,
SubCategory1,
(
case
when good_record_count = all_record_count then 1
else 0
end
) as all_records_good
from (
select
t.Category,
t.SubCategory1,
sum( cast(coalesce(t.Status, 'GOOD', '1', '0') as int) ) good_record_count,
count(1) all_record_count
from
table_name t
group by
t.Category, t.SubCategory1
)