I have a table with columns(id, name, total, timestamp) column. I wish to obtain data for total per week, per candidate with postgreSQL.
For example
Date, total, name (columns)
Jan 16-23, 23 , Marcus
Jan 16-23, 21 , Dennis
Jan 16-23, 18 , Sydney
Jan 23-39, 14, Marcus
Jan 23-39, 13, Dennis
Jan 23-39, 12, Sydney
Jan 30- Feb 5, 10, Marcus
Jan 30- Feb 5, 14, Dennis
Jan 30- Feb 5, 21, Sydney
How can I achieve this?
Related
I have 5 mandatory courses which is [ Python, Java, Kotlin, SQL, React ]. And I have different tables
Table name : dbo.course
course_id
course_name
mandatory
category_id
1
python
yes
20
2
java
yes
20
3
kotlin
yes
20
4
sql
yes
20
5
react
yes
20
6
c++
no
21
7
git
no
22
8
vb.net
no
23
table name : Table name : dbo.category which is linked to dbo.course
category_id
category_name
20
Dev
21
Bridge
22
PM
23
Bas
Table name : dbo.attendance (p = present , a = absent)
participant_id
status
course_id
log_in_date
log_out_date
1
p
1
july 2021
july 2021
1
p
2
july 2021
july 2021
1
p
3
july 2021
july 2021
1
p
4
july 2021
july 2021
1
p
5
july 2021
july 2021
2
p
1
july 2021
july 2021
3
a
6
null
null
4
a
8
null
null
5
p
1
july 2021
july 2021
5
p
2
july 2021
july 2021
5
p
3
july 2021
july 2021
5
p
4
july 2021
july 2021
5
p
5
july 2021
july 2021
if the participant finished all the mandatory courses then it will count as 1 and if not, it will not count unless he/she finish the training. I want the output something like this : Assume that there is 5 participant that finished the training in August 2021 and 10 participant in September 2021
select date,count(participant), count(*)
date
participant
count
july 2021
2
2
august 2021
5
7
september 2021
10
17
I have a column called anchor which is a timestamp. I have a row with value of jan 30 2020. I want to compare this to feb 29 2020, and it should give me 1 month. Even though its not 30 days, but feb has no more days after 29. I am trying to bill every month.
Here is my sql fiddle - http://sqlfiddle.com/#!17/6906d/2
create table subscription (
id serial,
anchor timestamp
);
insert into subscription (anchor) values
('2020-01-30T00:00:00.0Z'),
('2019-01-30T00:00:00.0Z');
select id,
anchor,
AGE('2020-02-29T00:00:00.0Z', anchor) as "monthsToFeb29-2020",
AGE('2019-02-28T00:00:00.0Z', anchor) as "monthsToFeb28-2019"
from subscription;
Is it possible to get age in the way I am speaking?
My expected results:
For age from jan 30 2020 to feb 29 2020 i expect 1.0 month
For age from jan 30 2020 to feb 28 2019 i expect -11.0 month
For age from jan 30 2019 to feb 29 2020 i expect 13.0 month
For age from jan 30 2019 to feb 28 2019 i expect 1.0 month
(this is how momentjs library does it for those node/js guys out there):
const moment = require('moment');
moment('Jan 30 2019', 'MMM DD YYYY').diff(moment('Feb 29 2020', 'MMM DD YYYY'), 'months', true) === -13.0
moment('Jan 30 2019', 'MMM DD YYYY').diff(moment('Feb 28 2019', 'MMM DD YYYY'), 'months', true) === -1.0
How about:
select round(('2/29/2020'::date - '1/30/2020'::date) / 30.0);
round
-------
1
select round(('02/28/2019'::date - '1/30/2020'::date ) / 30.0);
round
-------
-11
select round(('2/29/2020'::date - '1/30/2019'::date) / 30.0);
round
-------
13
select round(('2/28/2019'::date - '01/30/2019'::date) / 30.0);
round
-------
1
The date subtraction gives you a integer value of days, then you divide by a 30 day month and round to nearest integer. You could put this in a function and use that.
I run this report Mon-Fri for the previous day's data and I am trying to figure out how to hard code TO_CHAR(TRUNC(SYSDATE-3) if today is
Monday (day the report is run) or use TO_CHAR(TRUNC(SYSDATE-1) for any other workday (mon - fri). I am assuming that this will require an IF, THEN, ELSE statement but am unsure of how to include that properly into my query.
SELECT
RRA.LAST_MODIFICATION_DATE AS "LAST MODIFICATION DATE",
TO_CHAR(TRUNC(SYSDATE-1),'DD-MON-RR') AS "DATA_DATE"
FROM PHOENIX.R_REFERRAL_ACTIVITY RRA
Where 1=1
AND RRA.LAST_MODIFICATION_DATE
BETWEEN TO_CHAR(TRUNC(SYSDATE-1),'DD-MON-RR') AND TO_CHAR(TRUNC(SYSDATE),'DD-MON-RR')
Aha; OK then, it seems that you'd need to use CASE along with TO_CHAR function which will tell you which day is "today". Have a look, see if it helps.
TEST is just a simple calendar, several days in this February. I'm removing Saturdays and Sundays (as you said you're interested in mon - fri only).
SQL> with test as
2 (select trunc(sysdate, 'mm') + level - 1 c_date,
3 to_char(trunc(sysdate, 'mm') + level - 1, 'dy') c_day
4 from dual
5 connect by level < 20
6 )
7 select
8 c_date todays_date,
9 c_day,
10 --
11 c_date - case when c_day = 'mon' then 3
12 else 1
13 end previous_work_date,
14 --
15 to_char(c_date - case when c_day = 'mon' then 3
16 else 1
17 end, 'dy') previous_work_day
18 from test
19 where c_day not in ('sat', 'sun')
20 order by 1;
TODAYS_DAT C_D PREVIOUS_W PRE
---------- --- ---------- ---
01.02.2018 thu 31.01.2018 wed
02.02.2018 fri 01.02.2018 thu
05.02.2018 mon 02.02.2018 fri
06.02.2018 tue 05.02.2018 mon
07.02.2018 wed 06.02.2018 tue
08.02.2018 thu 07.02.2018 wed
09.02.2018 fri 08.02.2018 thu
12.02.2018 mon 09.02.2018 fri
13.02.2018 tue 12.02.2018 mon
14.02.2018 wed 13.02.2018 tue
15.02.2018 thu 14.02.2018 wed
16.02.2018 fri 15.02.2018 thu
19.02.2018 mon 16.02.2018 fri
13 rows selected.
SQL>
This example takes a base date and adds 7½ hours, 1 day 7½ hours, 2 days 7½ hours, and so on.
use Date::Manip;
use DateTime;
use DateTime::Format::DateManip;
Date::Manip::Date_Init("TZ=America/New_York", "Language=English");
my $otime = DateTime->new(
year => 2013,
month => 3,
day => 4,
hour => 0,
minute => 0,
second => 0,
time_zone => 'America/New_York',
);
my $t1 = UnixDate($otime, "%i:%M %p on %A, %B %e, %Y ");
print "original $t1\n";
for (my $i = 0; $i <= 20; $i++) {
my $dtw = $otime->clone();
$dtw->add(
minutes => (15) * 30,
days => ($i),
);
$t1 = UnixDate($dtw, "%i:%M %p on %A, %B %e, %Y ");
print "$i days $t1\n";
}
When adding 6 days 7½ hours, the result contains an extra hour.
original 12:00 AM on Monday, March 04, 2013
0 days 07:30 AM on Monday, March 04, 2013
1 days 07:30 AM on Tuesday, March 05, 2013
2 days 07:30 AM on Wednesday, March 06, 2013
3 days 07:30 AM on Thursday, March 07, 2013
4 days 07:30 AM on Friday, March 08, 2013
5 days 07:30 AM on Saturday, March 09, 2013
6 days 08:30 AM on Sunday, March 10, 2013 # why 8:30 and not 7:30?
7 days 07:30 AM on Monday, March 11, 2013
8 days 07:30 AM on Tuesday, March 12, 2013
9 days 07:30 AM on Wednesday, March 13, 2013
10 days 07:30 AM on Thursday, March 14, 2013
11 days 07:30 AM on Friday, March 15, 2013
12 days 07:30 AM on Saturday, March 16, 2013
13 days 07:30 AM on Sunday, March 17, 2013
14 days 07:30 AM on Monday, March 18, 2013
15 days 07:30 AM on Tuesday, March 19, 2013
16 days 07:30 AM on Wednesday, March 20, 2013
17 days 07:30 AM on Thursday, March 21, 2013
18 days 07:30 AM on Friday, March 22, 2013
19 days 07:30 AM on Saturday, March 23, 2013
20 days 07:30 AM on Sunday, March 24, 2013
Because Daylight Saving Time begins on March 10, 2013 in the America/New_York timezone. DateTime first adds $i days (to get midnight on March 10) and then adds 450 minutes to get 8:30 AM (because the minute after 1:59 AM on March 10 is 3:00 AM). The order of the parameters to add is not meaningful; see Adding a Duration to a Datetime.
Because it adds days & minutes separately (and processes the days first), the effect only happens on the date when DST actually begins or ends. If you want a particular time, just set it directly instead of using add. Or call add twice, once to add minutes, then again to add days.
I'm storing a collection of dates which are the previous 12 months starting from the beginning of the month. So I have:
my #t = localtime time();
my $m = $t[4];
my $y = $t[5];
foreach my $date (keys %$dates_ref) {
$m -= $comparison{$date}; # a hash of numbers to go back the correct number of months
$dates_ref->{$date} = mktime(0,0,0,1,$m,$y);
}
I end up with a bunch of dates like so:
Current month: 1356998400 which is:
Tue Jan 01 2013 00:00:00 GMT+0000 (GMT Standard Time)
Last 12 months:
1325376000 - Sun Jan 01 2012 00:00:00 GMT+0000 (GMT Standard Time)
1328054400 - Wed Feb 01 2012 00:00:00 GMT+0000 (GMT Standard Time)
1330560000 - Thu Mar 01 2012 00:00:00 GMT+0000 (GMT Standard Time)
1333238400 - Sun Apr 01 2012 01:00:00 GMT+0100 (GMT Daylight Time)
1335830400 - Tue May 01 2012 01:00:00 GMT+0100 (GMT Daylight Time)
1338508800 - Fri Jun 01 2012 01:00:00 GMT+0100 (GMT Daylight Time)
1341100800 - Sun Jul 01 2012 01:00:00 GMT+0100 (GMT Daylight Time)
1343779200 - Wed Aug 01 2012 01:00:00 GMT+0100 (GMT Daylight Time)
1346457600 - Sat Sep 01 2012 01:00:00 GMT+0100 (GMT Daylight Time)
1349049600 - Mon Oct 01 2012 01:00:00 GMT+0100 (GMT Daylight Time)
1351728000 - Thu Nov 01 2012 00:00:00 GMT+0000 (GMT Standard Time)
1354320000 - Sat Dec 01 2012 00:00:00 GMT+0000 (GMT Standard Time)
As you can see, April to October have the GMT hour added on. What is the best way of getting it to not do this, so it just starts at 00:00?
E.g. 1333238400 would become 1333234800
you should use the DateTime module, and properly handle the time zones. This is an example:
my $dt = DateTime->new(
year => 2000,
month => 5,
day => 10,
hour => 15,
minute => 15,
time_zone => 'America/Los_Angeles',
);
print $dt->hour; # prints 15
$dt->set_time_zone( 'America/Chicago' );
print $dt->hour; # prints 17
If you're able to install CPAN modules, I'd suggest using Date::Calc - it will let you convert to GMT instead of to your local timezone,
use gmtime instead of localtime in the first line of your script