I use this SQL query to make status report by day:
CREATE TABLE TICKET(
ID INTEGER NOT NULL,
TITLE TEXT,
STATUS INTEGER,
LAST_UPDATED DATE,
CREATED DATE
)
;
Query:
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
How I can limit this query to last 7 days?
Also I would like to get the results split by day. Fow example I would like to group the first dates for 24 hours, second for next 24 hours and etc.
Expected result:
This might help:
SELECT TO_CHAR(t.created, 'YYYY-MM-DD') AS created_date,
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
WHERE t.created >= SYSDATE-7
GROUP BY TO_CHAR(t.created, 'YYYY-MM-DD')
ORDER BY created_date;
I used the oracle function for date conversion. I'm sure you'll find the corresponding one for postgresql.
Related
I need to calculate On Time Arrival and Departure. Query to get On Time Departure:
SELECT DEPAIRPORT as AIRPORT,
COUNT(case when A.STATUS = 'Scheduled' and
A.ACTUAL_BLOCKOFF is not null then 1 else NULL END) as SCHEDULED,
COUNT(case when ((A.ACTUAL_BLOCKOFF+ interval '7' hour) - (A.SCHEDULED_DEPDT+ interval '7' hour))*24*60 <= '+000000015 00:00:00.000000000' and
A.ACTUAL_BLOCKOFF is not null then 1 else NULL END) as ONTIME
FROM TABLE A GROUP BY DEPAIRPORT
and Query to calculate On Time Arrival:
SELECT COUNT(case when ((A.ACTUAL_BLOCKON + interval '7' hour) - (A.SCHEDULED_ARRDT+ interval '7' hour))*24*60 <= '+000000015 00:00:00.000000000' and
A.ACTUAL_BLOCKON is not null then 1 else NULL END) as ARRONTIME
FROM TABLE A
GROUP BY ARRIVALAIRPORT
How to combine these queries into 1 single query so I can display it like this table:
Name #Schedule #OnTimeDeparture #ArrivalOntime
AIRPORTX 41 35 20
Without the sample data and expected output, it is difficult to tell what exactly you want. If you want to combine the two datasets, you may put them in with clauses and the then join them together(LEFT JOIN or INNER JOIN based on the output required for cases where arrival has happened yet or not)
WITH dep
AS (SELECT depairport AS airport,
count(CASE
WHEN a.status = 'Scheduled'
AND a.actual_blockoff IS NOT NULL THEN 1
END) AS scheduled,
count(CASE
WHEN( ( a.actual_blockoff + interval '7' hour ) - (
a.scheduled_depdt + interval '7' hour ) ) *
24 *
60
<=
'+000000015 00:00:00.000000000'
AND a.actual_blockoff IS NOT NULL THEN 1
END) AS ontime
FROM tablea
GROUP BY depairport),
arr
AS (SELECT arrivalairport AS airport,
count(CASE
WHEN( ( a.actual_blockon + interval '7' hour ) - (
a.scheduled_arrdt + interval '7' hour ) ) *
24 *
60
<=
'+000000015 00:00:00.000000000'
AND a.actual_blockon IS NOT NULL THEN 1
END) AS arrontime
FROM tablea
GROUP BY arrivalairport)
SELECT dep.airport AS Name,
dep.scheduled AS "#Schedule",
dep.ontime AS "#OnTimeDeparture",
arr.arrontime AS "#ArrivalOntime"
FROM dep
left join arr -- Or Inner join depending on the expected output.
ON ( dep.airport = arr.airport );
You can use something like this:
select
max(SCHEDULED) as SCHEDULED,
max(ONTIME) as ONTIME,
max(ARRONTIME) as ARRONTIME
from (select
count(case when ... ) over(partition by DEPAIRPORT) as SCHEDULED,
count(case when ... ) over(partition by DEPAIRPORT) as ONTIME,
count(case when ... ) over(partition by ARRIVALAIRPORT) as ARRONTIME
from a );
But I guess that your question is not complete. Also you need a key for join different flights.
I'm trying to count my table by week but the DATE_TRUNCT('week',date) function considers Monday as the start of the week but I need for the week to start in Sunday.
This is the query, which runs properly but with starting in Mondays...
SELECT DATE_TRUNC('week',myDate) AS Reference,
column1 AS Item1,
column2 AS Item2,
COUNT(*) AS Volume,
COUNT(CASE WHEN status = 'status1' THEN 1 END) AS Status1,
COUNT(CASE WHEN status = 'status2' THEN 1 END) AS Status2,
COUNT(CASE WHEN status = 'status2' AND fase = '1' THEN 1 END) AS Fase1,
COUNT(CASE WHEN status = 'status2' AND fase = '2' THEN 1 END) AS Fase2,
COUNT(CASE WHEN status = 'status2' AND fase = '3' THEN 1 END) AS Fase3
FROM myTable
WHERE DATE_TRUNC('week',myDate) = DATE_TRUNC('week',TO_DATE('12/25/2016 00:00:00','MM/dd/yyyy'))
GROUP BY 1,
2,
3;
So far I only tried another query which doesnt even run and I dont know why, it just says "syntax error at or near "integer" :
SELECT DATE_TRUNC('week',myDate) - integer '1' AS Reference,
column1 AS Item1,
column2 AS Item2,
COUNT(*) AS Item3,
COUNT(CASE WHEN status = 'status1' THEN 1 END) AS Status1,
COUNT(CASE WHEN status = 'status2' THEN 1 END) AS Status2,
COUNT(CASE WHEN status = 'status2' AND fase = '1' THEN 1 END) AS Fase1,
COUNT(CASE WHEN status = 'status2' AND fase = '2' THEN 1 END) AS Fase2,
COUNT(CASE WHEN status = 'status2' AND fase = '3' THEN 1 END) AS Fase3
FROM myTable
WHERE myDate between ( DATE_TRUNC('week', TO_DATE('12/25/2016 00:00:00','MM/dd/yyyy' ) - integer '1' ) and ( DATE_TRUNC('week', TO_DATE('12/25/2016 00:00:00','MM/dd/yyyy' ) ) + integer '5' )
GROUP BY 1,
2,
3;
Also, even if this query runned propely, it would show the count of the week 18/Dec - 24/Dec and not the week 25/Dec - 31/Dec in the case 25/Dec. The same would happen in other days if they are Sundays.
EDIT:
I just found the solution in this blog:
https://blog.modeanalytics.com/date-trunc-sql-timestamp-function-count-on/
It was introducing the date_trunct function and someone asked the same question in the comments. This is my solved query for future reference to others:
SELECT date_trunc('WEEK',(myDate + interval '1 day'))- interval '1 day' AS Reference
column1 AS Item1,
column2 AS Item2,
COUNT(*) AS Volume,
COUNT(CASE WHEN status = 'status1' THEN 1 END) AS Status1,
COUNT(CASE WHEN status = 'status2' THEN 1 END) AS Status2,
COUNT(CASE WHEN status = 'status2' AND fase = '1' THEN 1 END) AS Fase1,
COUNT(CASE WHEN status = 'status2' AND fase = '2' THEN 1 END) AS Fase2,
COUNT(CASE WHEN status = 'status2' AND fase = '3' THEN 1 END) AS Fase3
FROM myTable
WHERE ( date_trunc('WEEK',(myDate + interval '1 day'))- interval '1 day') = ( DATE_TRUNC('week',TO_DATE('12/24/2016 00:00:00','MM/dd/yyyy') + interval '1 day' ) - interval '1 day' )
GROUP BY 1,
2,
3;
I couldn't find any simple way to set week as Sunday to Saturday. But you can try this:
select date_trunc('week', myDate + 1) - 1 as Reference,
...
from myTable
where ...
group by date_trunc('week', myDate + 1), ...
The trick here is just shift by one day while doing group by.
I've two query from same table but by two condition but how can I make two column for this two conditional count.
SELECT Count(*) FROM TBL_FT WHERE STATUS = 'X';
SELECT Count(*) FROM TBL_FT WHERE STATUS = 'Y' and
LOGDATE>trunc(sysdate);
You can use conditional aggregation:
SELECT
COUNT(CASE WHEN STATUS = 'X' THEN 1 END),
COUNT(CASE WHEN STATUS = 'Y' AND LOGDATE > trunc(sysdate) THEN 1 END)
FROM TBL_FT
You can also add a WHERE clause:
WHERE STATUS IN ('X', 'Y');
you can use something like this -
SELECT SUM(CASE
WHEN STATUS = 'X' THEN
1
ELSE
0
END) FIRST_VAL,
SUM(CASE
WHEN STATUS = 'Y'
AND LOGDATE > TRUNC(SYSDATE) THEN
1
ELSE
0
END) second_val
FROM TBL_FT;
I have the following query:
select
fp.id,
fr.id,
sum(case
when to_date(fp.offered_date) BETWEEN TO_DATE( :ad_startdate, 'YYYY-MM-DD')
AND TO_DATE(:ad_enddate, 'YYYY-MM-DD') and fp.result <> 'E'
then 1
else 0
end) total,
sum(case when fp.result = 'G'
and to_date(fp.offered_date) >= :ad_startdate
and to_date(fp.offered_date) <= :ad_enddate then 1 else 0 end) colorgreen,
sum(case when fp.resultat = 'R'
and to_date(fp.offered_date) >= :ad_startdate
and to_date(fp.offered_date) <= :ad_enddate then 1 else 0 end) colorred
FROM
fruit_properties fp, fruit fr
WHERE
fp.id = fr.id
GROUP BY
fp.id, fr.id
I'm checking dates 1 time for each sum column and have a feeling this can be made once somehow? Right now if I check only once at the total column, then colorgreen + colorred might be larger than the total since it counts no matter what date they have.
Can my query be enhanced somehow?
you can simplify like this. but PLEASE check your SQL. you're mixing TO_DATE and CHAR datatypes. this will only end in disaster.
eg you have:
when to_date(fp.offered_date) BETWEEN TO_DATE( :ad_startdate, 'YYYY-MM-DD')
AND TO_DATE(:ad_enddate, 'YYYY-MM-DD')
vs
sum(case when fp.result = 'G'
and to_date(fp.offered_date) >= :ad_startdate
in one case you are TO_DATE'ing ad_startdate but not another (so is it a date already or not?). you are also TO_DATEing the column but crucially WITHOUT a format mask. is the column really a VARCHAR datatype? if so you really should not store dates as anything but DATEs.
anyway assuming the column is a DATE datatype and the binds are of type DATE..
select fruit_prop_Id,fruit_id,
sum(case when result != 'E' then within_offer else 0 end) total,
sum(case when result = 'R' then within_offer else 0 end) colorred,
sum(case when result = 'G' then within_offer else 0 end) colorgreen
from (select fp.id fruit_id,
fr.id fruit_prop_Id,
fp.result,
case
when fp.offered_date >= :ad_startdate
and fp.offered_date <= :ad_enddate then 1 else 0 end within_offer
from fruit_properties fp, fruit fr
where fp.id = fr.id)
group by fruit_id, fruit_prop_Id
You can put the date check in the where clause:
select
fp.id,
fr.id,
sum(case when and fp.result <> 'E' then 1 else 0 end) total,
sum(case when fp.result = 'G' then 1 else 0 end) colorgreen,
sum(case when fp.resultat = 'R' then 1 else 0 end) colorred
FROM
fruit_properties fp, fruit fr
WHERE
fp.id = fr.id
AND to_date(fp.offered_date) >= :ad_startdate
AND to_date(fp.offered_date) <= :ad_enddate
GROUP BY
fp.id, fr.id
Edit: as pointed out in the comments, this query will filter out ids which doesn't have any offer dates in the given interval.
the goal is to retrieve the number of users in one table which have:
field EXPIREDATE > CURRENT_TIMESTAMP as nUsersActive
field EXPIREDATE < CURRENT_TIMESTAMP as nUsersExpired
field EXPIREDATE IS NULL as nUsersPreregistered
all with one query, and the result should for example be
nUsersActive nUsersExpired nUsersPreregistered
10 2 15
this will later be json_encoded and passed to an ExtJS script for displaying.
Any hint? I tried several times without succeding. I tried with the UNION statement, I get the right numbers, but of course in column, while I need them in row.
Thanks for your support.
Something like the following should work, you may need to adjust for the specific database that you are using.
To get them in columns:
select
count(case when EXPIREDATE > CURRENT_TIMESTAMP then 1 end) AS nUsersActive,
count(case when EXPIREDATE < CURRENT_TIMESTAMP then 1 end) AS nUsersExpired,
count(case when EXPIREDATE IS NULL then 1 end) AS nUserPreregistered
from users_table
And in rows (this is not as efficient!):
select
'nUsersActive' AS Param
count(case when EXPIREDATE > CURRENT_TIMESTAMP then 1 end) AS Value
from users_table
UNION ALL
select 'nUsersExpired',
count(case when EXPIREDATE < CURRENT_TIMESTAMP then 1 end)
from users_table
UNION ALL
select 'nUserPreregistered',
count(case when EXPIREDATE IS NULL then 1 end)
from users_table
I'm assuming you are using SQL Server. You should be able to get what you're looking for by using a CASE statement. Make sure you return something (anything) if the condition is true and NULL if the condition is false. Here is the msdn documentation: http://msdn.microsoft.com/en-us/library/ms181765.aspx
Your query would look something like this:
select COUNT(CASE WHEN #ThingToCheck = 'Value' THEN 1 ELSE NULL END) as Count1, COUNT(CASE WHEN #ThingToCheck = 'Value' THEN 1 ELSE NULL END) FROM ....
SELECT COUNT(CASE WHEN EXPIREDATE > CURRENT_TIMESTAMP THEN 1 END) AS nUsersActive,
COUNT(CASE WHEN EXPIREDATE < CURRENT_TIMESTAMP THEN 1 END) AS nUsersExpired,
COUNT(CASE WHEN EXPIREDATE IS NULL THEN 1 END) AS nUsersPreregistered
FROM Users