Count all rows by status and day - sql

I want to use this table to store tickets in PostgreSQL.
CREATE TABLE TICKET(
ID INTEGER NOT NULL,
TITLE TEXT,
STATUS INTEGER,
LAST_UPDATED DATE,
CREATED DATE
)
;
I use column 'status' to set different status(1, 2, 3, 4). How I can count all tickets by status and day with one SQL query?
I would like to get the final result for example like simple array of numbers:
32 31 23 42 9.11.215
31 21 13 22 10.11.215
3 3 2 43 11.11.215

You can doing it with conditional aggregation, which will unite separate rows into 1 aggregated row :
SELECT t.created,
COUNT(CASE WHEN t.status = '1' THEN 1 END) as cnt_status1,
COUNT(CASE WHEN t.status = '2' THEN 1 END) as cnt_status2,
COUNT(CASE WHEN t.status = '3' THEN 1 END) as cnt_status3,
COUNT(CASE WHEN t.status = '4' THEN 1 END) as cnt_status4
FROM ticket t
GROUP BY t.created

Related

psql how to turn group by functions into columns

I have the following table:
ID Day Count
1 '1' 1
1 '2' 2
1 '2' 7
2 '2' 4
2 '2' 3
and I'm doing the following query:
select ID, Day, sum(Count) from test_table group by ID, Day
and I get the following table:
ID Day Count
1 '1' 1
1 '2' 9
2 '2' 7
what I want is
ID Day1 Day2
1 1 9
2 0 7
How do I do that?
I would just use conditional aggregation:
select ID,
sum(case when day = 1 then count else 0 end) as day_1,
sum(case when day = 2 then count else 0 end) as day_2
from test_table
group by ID;
Use crosstab() from the tablefunc module.
Something like this:
SELECT *
FROM crosstab(
$$select ID, Day, sum(Count)
from foo2
where Day = '1' or Day = '2'
group by ID, Day
order by 1,2$$)
AS ct(ID int, day_1 BIGINT, day_2 BIGINT);

SQL to calculate Net Capacity

How to write a SQL to get the Net change in capacity by using the capacity (when status is 1 or 2) and minus the total capacity (when status is 3) for each month? Thanks. Here is the table:
STATUS MONTH CAPACITY
1 01/16 5
3 01/16 2
1 02/16 11
3 02/16 20
1 03/16 8
3 03/16 12
1 04/16 4
2 04/16 10
3 04/16 18
2 05/16 14
3 05/16 37
2 06/16 4
3 06/16 8
For example, the net change in capacity for Jan. 16 is 5 minus 2 equals 3.
You need a conditional sum:
SUM(CASE WHEN STATUS IN (1,2) THEN CAPACITY ELSE 0 END) -
SUM(CASE WHEN STATUS IN (3) THEN CAPACITY ELSE 0 END)
dnoeth answer can be simplified to
SUM(CASE WHEN STATUS IN (1,2) THEN CAPACITY WHEN STATUS IN (3) THEN -CAPACITY ELSE 0 END)
Builds on 1,2 < 3
select MONTH, [Net change]=SUM(CASE STATUS/3 WHEN 0 THEN CAPACITY ELSE -CAPACITY END)
from t
group by MONTH;
no CASE statement:
select month, sum(capacity)-2*sum((status/3)*capacity) from table group by month;
Here is an example
You can join the table to itself and perform the calculation like so:
SELECT
a.status,
a.month,
a.capacity,
b.capacity AS total_capacity,
a.capacity - b.capacity AS net_capacity
FROM
table a
JOIN
table b
ON (a.month = b.month)
AND (b.status = 3)
WHERE
a.status IN (1,2);
-- If you don't want to have the status and instead aggregate in the event there are two within the same month:
SELECT
a.month,
SUM(a.capacity) AS capacity,
SUM(b.capacity) AS total_capacity,
SUM(a.capacity) - MAX(b.capacity) AS net_capacity
FROM
table a
JOIN
table b
ON (a.month = b.month)
AND (b.status = 3)
WHERE
a.status IN (1,2)
GROUP BY
a.month;
SELECT
"Status",
"Month",
SUM(Capacity) AS Capacity
FROM ( SELECT
"Status",
"Month",
CASE WHEN Status = 3 THEN -1 * Capacity ELSE Capacity END AS Capacity FROM tbl
) t
GROUP BY
"Status",
"Month"

Count Values from Table for each type

I have the following table
UserId [nvarchar(128)], Rating [varchar(170)] :values will be mostly 1,2,3 but can have exceptions
Rating contains 3 values [1,2, or 3]
I want to get a result something like
UserId Count(1's),Count(2's) Count(3's)
1. 1001 10 8 2
2. 1002 5 10 3
Is it possible in a single query
Do a GROUP BY UserId to count for each user-id. Use CASE to count 1's, 2's and 3's separately:
select UserId,
count(case when Rating = 1 then 1 end) as [Count(1's)],
count(case when Rating = 2 then 1 end) as [Count(2's)],
count(case when Rating = 3 then 1 end) as [Count(3's)]
from tablename
group by UserId
Use a CASE statement in each COUNT and then GROUP BY UserId.
SELECT UserId, COUNT(CASE WHEN value = '1' THEN 1 END) AS [Count(1's)], COUNT(CASE WHEN value = '2' THEN 1 END) AS [Count(2's)], COUNT(CASE WHEN value = '3' THEN 1 END) AS [Count(3's)]
FROM yourtable
GROUP BY UserId
Use PIVOT:
SELECT
UserId,
COALESCE([1],0) [Count(1's)],
COALESCE([2],0) [Count(2's)],
COALESCE([3],0) [Count(3's)]
FROM
ýour_table
PIVOT
(COUNT([Rating])
FOR Rating
in([1],[2],[3])
)AS p
ORDER BY
UserId

JOIN the same table

Hi I have table badge which has columns facility and date (other columns are not important).
I want to select count(*) which should look like this:
DATE | FACILITY 4 COUNT | FACILITY 1 COUNT
12/12/2012 | 234 | 647
I wrote two separate queries for facility 1 and 4 but how to join it to one Query;
SELECT
date,
COUNT(*)
FROM badge
WHERE facility = 3
AND xtype = 19
AND date BETWEEN 'some_date' AND 'some_date'
GROUP BY date
another query differs only in the value of facility.
EDIT: It's informix database.
SELECT date,
SUM(case when facility = 1 then 1 else 0 end) "FACILITY 1 COUNT",
SUM(case when facility = 4 then 1 else 0 end) "FACILITY 4 COUNT"
FROM badge
WHERE (facility = 1 OR facility = 4)
AND xtype = 19
AND date BETWEEN 'some_date' AND 'some_date'
GROUP BY date
give this a try,
SELECT date,
SUM(CASE WHEN facility = 3 THEN 1 ELSE 0 END) `Facility 3 Count`,
SUM(CASE WHEN facility = 1 THEN 1 ELSE 0 END) `Facility 1 Count`
FROM badge
WHERE xtype = 19 AND
date BETWEEN 'some_date' AND 'some_date'
GROUP BY date

AVG and Count from one columns

I Have a table by this Columns :
[Student_ID],[Class_ID],[Techer_ID],[Course_ID],[Marks]
and for range of marks exist name for example:
between 0 to 5 = D
between 6 to 10 = C
between 11 to 15 = B
between 16 to 20 = A
Now i need create T-Sq l Query for Return this result message columns:
Teacher_ID|Course_ID|Count(Marks)|Count(A)| Count(B)|Count(C)|Count(D)
Very thanks for your help
select Teacher_ID
, Course_ID
, count(*)
, sum(case when Marks between 16 and 20 then 1 end) as SumA
, sum(case when Marks between 11 and 15 then 1 end) as SumB
, sum(case when Marks between 6 and 10 then 1 end) as SumC
, sum(case when Marks between 0 and 5 then 1 end) as SumD
from YourTable
group by
Teacher_ID
, Course_ID
I would use the same approach as Andomar, only change sum to count like this:
select Teacher_ID
, Course_ID
, count(*)
, count(case when Marks between 16 and 20 then 1 end) as countA
, count(case when Marks between 11 and 15 then 1 end) as countB
, count(case when Marks between 6 and 10 then 1 end) as countC
, count(case when Marks between 0 and 5 then 1 end) as countD
from YourTable
group by
Teacher_ID
, Course_ID
In my opinion, the query looks more natural this way.
You can do this with PIVOT. (Note also that this formulation of the Marks-to-Letter calculation is a bit safer than one where both ends of each range must be typed.)
with T as (
select
Teacher_ID,
Course_ID,
case
when Marks <= 5 then 'countD'
when Marks <= 10 then 'countC'
when Marks <= 15 then 'countB'
else 'countA' end as Letter
from T
)
select
Teacher_ID,
Course_ID,
countD+countC+countB+countA as countMarks,
countA,
countB,
countC,
countD
from T pivot (
count(Letter) for Letter in ([countA],[countB],[countC],[countD])
) as P