I have a table in PostgreSQL
time
goals
assists
2022-03-01 00:00:00
22
1
2022-03-03 00:00:00
24
2
2022-03-07 00:00:00
25
3
I want to add missing timestamps and fill the goals and assists in, as displayed in the table below
time
goals
assists
2022-03-01 00:00:00
22
1
2022-03-02 00:00:00
22
1
2022-03-03 00:00:00
24
2
2022-03-04 00:00:00
24
2
2022-03-05 00:00:00
24
2
2022-03-06 00:00:00
24
2
2022-03-07 00:00:00
25
3
Related
I have a calendar table where working days are marked.
Now I need a running total called "current_working_day" which sums up the working days until the end of a month and restarts again.
This is my query:
select
WDAYS.Date,
WDAYS.DayName,
WDAYS.WorkingDay,
sum(WDAYS.WorkingDay) OVER(order by (Date), MONTH(Date), YEAR(Date)) as 'current_working_day',
sum(WDAYS.WorkingDay) OVER(PARTITION by YEAR(WDAYS.Date), MONTH(WDAYS.Date) ) total_working_days_per_month
from WDAYS
where YEAR(WDAYS.Date) = 2022
This is my current output
Date
DayName
WorkingDay
current_working_day
total_working_days_per_month
2022-01-27
Thursday
1
19
21
2022-01-28
Friday
1
20
21
2022-01-29
Saturday
0
20
21
2022-01-30
Sunday
0
20
21
2022-01-31
Monday
1
21
21
2022-02-01
Tuesday
1
22
20
2022-02-02
Wednesday
1
23
20
2022-02-03
Thursday
1
24
20
But the column "current_workind_day" should be like this
Date
DayName
WorkingDay
current_working_day
total_working_days_per_month
2022-01-27
Thursday
1
19
21
2022-01-28
Friday
1
20
21
2022-01-29
Saturday
0
20
21
2022-01-30
Sunday
0
20
21
2022-01-31
Monday
1
21
21
2022-02-01
Tuesday
1
1
20
2022-02-02
Wednesday
1
2
20
2022-02-03
Thursday
1
3
20
Thanks for any advice.
You can try to use PARTITION by with EOMONTH function which might get the same result but better performance, then you might only need to order by Date instead of using the function with the date.
select
WDAYS.Date,
WDAYS.DayName,
WDAYS.WorkingDay,
sum(WDAYS.WorkingDay) OVER(PARTITION by EOMONTH(WDAYS.Date) order by Date) as 'current_working_day',
sum(WDAYS.WorkingDay) OVER(PARTITION by EOMONTH(WDAYS.Date) ) total_working_days_per_month
from WDAYS
where YEAR(WDAYS.Date) = 2022
I have a DateTime dimension with dates like this:
Datetime Date hour
--------------------------------------
2026-01-01 00:00:00.0000000 24
2025-12-31 23:00:00.0000000 23
2025-12-31 22:00:00.0000000 22
2025-12-31 21:00:00.0000000 21
2025-12-31 20:00:00.0000000 20
2025-12-31 19:00:00.0000000 19
2025-12-31 18:00:00.0000000 18
2025-12-31 17:00:00.0000000 17
2025-12-31 16:00:00.0000000 16
2025-12-31 15:00:00.0000000 15
2025-12-31 14:00:00.0000000 14
2025-12-31 13:00:00.0000000 13
2025-12-31 12:00:00.0000000 12
2025-12-31 11:00:00.0000000 11
2025-12-31 10:00:00.0000000 10
2025-12-31 09:00:00.0000000 9
2025-12-31 08:00:00.0000000 8
2025-12-31 07:00:00.0000000 7
2025-12-31 06:00:00.0000000 6
2025-12-31 05:00:00.0000000 5
2025-12-31 04:00:00.0000000 4
2025-12-31 03:00:00.0000000 3
2025-12-31 02:00:00.0000000 2
2025-12-31 01:00:00.0000000 1
Due to systemtime i need that my hours start at 6 o'clock instead, but how do i do that? I could create a temptable with hardcoded values and join on, but theres gotta be a simpler way?
Desired result:
Datetime Date hour
--------------------------------------
2026-01-01 00:00:00.0000000 19
2025-12-31 23:00:00.0000000 18
2025-12-31 22:00:00.0000000 17
2025-12-31 21:00:00.0000000 16
2025-12-31 20:00:00.0000000 15
2025-12-31 19:00:00.0000000 14
2025-12-31 18:00:00.0000000 13
2025-12-31 17:00:00.0000000 12
2025-12-31 16:00:00.0000000 11
2025-12-31 15:00:00.0000000 10
2025-12-31 14:00:00.0000000 9
2025-12-31 13:00:00.0000000 8
2025-12-31 12:00:00.0000000 7
2025-12-31 11:00:00.0000000 6
2025-12-31 10:00:00.0000000 5
2025-12-31 09:00:00.0000000 4
2025-12-31 08:00:00.0000000 3
2025-12-31 07:00:00.0000000 2
2025-12-31 06:00:00.0000000 1
2025-12-31 05:00:00.0000000 24
2025-12-31 04:00:00.0000000 23
2025-12-31 03:00:00.0000000 22
2025-12-31 02:00:00.0000000 21
2025-12-31 01:00:00.0000000 20
And for any questions about why I dont hold a DateDimension and a
TimeDimension. This cannot forefill my requirements since I have many
more business rules on my datetime dimensions
At a guess...
UPDATE YourTable
SET [Date hour] = IIF(DATEPART(HOUR,DATEADD(HOUR, -5, [datetime])) = 0,24,DATEPART(HOUR,DATEADD(HOUR, -5, [datetime]));
Given that your [Date hour] column is already computed, you may try updating using the modulus:
UPDATE yourTable
SET [Date hour] = 1 + ([Date hour] + 18) % 24;
Demo
A better long term solution might be to make your date hour column a computed column, based on the original date time information. Se the answer by #Larnu for one way to do this.
I have a SQL query where I am getting the row number for a count of employees per division and per month at the beginning of the month and the end of the month. To do that, I use a payroll end date which is a weekly date. So in essence I have 4 dates where employee counts are shown. Some months have 5 dates which makes the row count for that month 5 instead of 4.
I then need to build an SSRS report to show only the first employee count and the last employee count per division, per month. I have the first number since I am using =IIF(Fields!RowNumber.Value = 1, Fields!EMPCOUNT.Value, 0)
The problem I have now is getting the last employee count where I need to conditionally select a count where row number needs to be 5 if exists or 4 if it doesn't exist. I'm not sure how to get the expression to work in SSRS. Sample data is below.
PRCo EMPCOUNT udDivision PREndDate ROWNUM Type
1 89 Civil 2018-01-06 00:00:00 1 1
1 97 Civil 2018-01-13 00:00:00 2 1
1 97 Civil 2018-01-20 00:00:00 3 1
1 97 Civil 2018-01-27 00:00:00 4 1
1 16 Colorado 2018-01-06 00:00:00 1 1
1 18 Colorado 2018-01-13 00:00:00 2 1
1 14 Colorado 2018-01-20 00:00:00 3 1
1 10 Colorado 2018-01-27 00:00:00 4 1
1 94 Civil 2018-02-03 00:00:00 1 2
1 91 Civil 2018-02-10 00:00:00 2 2
1 92 Civil 2018-02-17 00:00:00 3 2
1 91 Civil 2018-02-24 00:00:00 4 2
1 16 Colorado 2018-02-03 00:00:00 1 2
1 16 Colorado 2018-02-10 00:00:00 2 2
1 18 Colorado 2018-02-17 00:00:00 3 2
1 19 Colorado 2018-02-24 00:00:00 4 2
1 92 Civil 2018-03-03 00:00:00 1 3
1 91 Civil 2018-03-10 00:00:00 2 3
1 88 Civil 2018-03-17 00:00:00 3 3
1 92 Civil 2018-03-24 00:00:00 4 3
1 90 Civil 2018-03-31 00:00:00 5 3
1 19 Colorado 2018-03-03 00:00:00 1 3
1 26 Colorado 2018-03-10 00:00:00 2 3
1 25 Colorado 2018-03-17 00:00:00 3 3
1 27 Colorado 2018-03-24 00:00:00 4 3
1 24 Colorado 2018-03-31 00:00:00 5 3
I would do this in your query rather than trying to get it to work directly in SSRS. There might be a simpler way than this but this is just based on your existing query.
Please note this is untested and just off the top of my head so it may need some editing before it will work.
SELECT * INTO #t FROM YOUR_EXISTING_QUERY
SELECT DISTINCT
PRCo
, udDivision
, YEAR(PREndDate) AS Yr
, MONTH(PREndDate) AS Mnth
, FIRST_VALUE(EMPCOUNT) OVER(PARTITION BY PRCo, udDivision, YEAR(PREndDate), MONTH(PREndDate) ORDER BY ROWNUM) AS OpeningEMPCOUNT
, LAST_VALUE(EMPCOUNT) OVER(PARTITION BY PRCo, udDivision, YEAR(PREndDate), MONTH(PREndDate) ORDER BY ROWNUM) AS CLosing_EMPCOUNT
FROM #t
Yo might need to include Type not sure what this does but you get the idea hopefully.
The FIRST_VALUE and LAST_VALUE functions simply get the first/last value within the partition defined, in your case PRCo, udDivision and then just the year and month portion of the payroll end date, the first and last positions are determined by the order clause, in this case row number.
This question already has answers here:
Sql Date Grouping with avaliable dates in database
(3 answers)
Closed 4 years ago.
ID DateTime EmailCount
93 6/1/2014 00:00:00 4
94 6/2/2014 00:00:00 4
95 6/3/2014 00:00:00 2
96 6/4/2014 00:00:00 2
97 6/5/2014 00:00:00 2
98 6/6/2014 00:00:00 2
99 6/7/2014 00:00:00 2
73 6/8/2014 00:00:00 2
74 6/9/2014 00:00:00 2
75 6/10/2014 00:00:00 4
76 6/11/2014 00:00:00 4
77 6/12/2014 00:00:00 2
78 6/13/2014 00:00:00 2
79 6/14/2014 00:00:00 2
80 6/16/2014 00:00:00 2
81 6/17/2014 00:00:00 4
82 6/18/2014 00:00:00 4
83 6/19/2014 00:00:00 4
84 6/20/2014 00:00:00 4
100 6/21/2014 00:00:00 4
101 6/22/2014 00:00:00 4
102 6/23/2014 00:00:00 4
103 6/24/2014 00:00:00 4
89 6/27/2014 00:00:00 4
90 6/28/2014 00:00:00 4
91 6/29/2014 00:00:00 4
92 6/30/2014 00:00:00 4
104 7/1/2014 00:00:00 4
105 7/2/2014 00:00:00 4
106 7/3/2014 00:00:00 4
121 7/6/2014 00:00:00 2
122 7/7/2014 00:00:00 2
123 7/8/2014 00:00:00 2
Generated Output
Startdate EndDate EmailCount
6/3/2014 00:00:00 6/14/2014 00:00:00 2
6/16/2014 00:00:00 6/16/2014 00:00:00 2
7/6/2014 00:00:00 7/8/2014 00:00:00 2
6/1/2014 00:00:00 6/11/2014 00:00:00 4
6/17/2014 00:00:00 6/24/2014 00:00:00 4
6/27/2014 00:00:00 7/3/2014 00:00:00 4
Here, the generated output is not perfect because I want StartDate to EndDate in groups like: (6/3/2014 to 6/9/2014 and EmailCount = 2) and (6/10/2014 to 6/11/2014 and EmailCount =4) and (6/12/2014 to 6/14/2014 and EmailCount =2). Also, date not in database should not be added to group.
A somewhat complex query to explain, but here goes an attempt;
If the time is always midnight, you could use a common table expression to assign a row number to each row, and group by the difference between the date and row number. As long as the sequence is not broken (ie the dates are consecutive and with the same emailid) they will end up in the same group and an outer query can easily extract the start and end date for each group;
WITH cte AS (
SELECT dateandtime, emailid,
ROW_NUMBER() OVER (PARTITION BY emailid ORDER BY dateandtime) rn
FROM mytable
)
SELECT MIN(dateandtime) start_time,
MAX(dateandtime) end_time,
MAX(emailid) emailid
FROM cte GROUP BY DATEADD(d, -rn, dateandtime) ORDER BY start_time
An SQLfiddle to test with.
If the datetimes are not always midnight, the grouping will fail. If that's the case, you could add a common table expression that converts the datetime to a date as a separate step before running this query.
You're looking for runs of consecutive dates in blocks with the same EmailID. This assumes you have no gaps in the dates. I'm not sure it's the most elegant approach but you can find a lot of stuff on this topic.
with BlockStart as (
select t.StartDate, t.EmailID
from T as t left outer join T as t2
on t2.StartDate = t1.StartDate - 1 and t2.EmailID = t1.EmailID
where t2.StartDate is null
union all
select max(StartDate) + 1, null
from T
) as BlockStart
select
StartDate,
(select min(StartDate) - 1 from BlockStart as bs2 where bs2 > bs.StartDate) as EndDate,
EmailID
from BlockStart as bs
where
EmailID is not null
-- /* or */ exists (select 1 from BlockStart as bs3 where bs3.StartDate > bs.StartDate)
This question already has answers here:
Count Query required [closed]
(3 answers)
Closed 8 years ago.
ID Time Status
----------- ----------------------- --------------------------------------------------
1 2013-12-24 00:00:00 on
2 2013-12-25 00:00:00 on
3 2013-12-26 00:00:00 on
4 2013-12-27 00:00:00 on
5 2013-12-28 00:00:00 on
6 2013-12-29 00:00:00 on
7 2013-12-30 00:00:00 on
8 2013-12-31 00:00:00 on
9 2013-12-24 00:00:00 off
10 2013-12-25 00:00:00 off
11 2013-12-27 00:00:00 off
12 2013-12-27 00:00:00 on
13 2013-12-27 00:00:00 off
14 2013-12-27 00:00:00 on
15 2013-12-27 00:00:00 off
16 2013-12-28 00:00:00 on
17 2013-12-28 00:00:00 off
18 2013-12-28 00:00:00 on
19 2013-12-29 00:00:00 off
20 2013-12-29 00:00:00 on
21 2013-12-30 00:00:00 off
22 2013-12-30 00:00:00 on
23 2013-12-30 00:00:00 off
24 2013-12-30 00:00:00 on
25 2013-12-30 00:00:00 off
26 2013-12-31 00:00:00 on
27 2013-12-31 00:00:00 off
28 2013-12-31 00:00:00 on
29 2013-12-31 00:00:00 off
30 2013-12-31 00:00:00 on
31 2013-12-31 00:00:00 off
My table name is abc and I want to arrange data datewise and status wise with counts of on and counts of off datewise
Select time, SUM(on_cnt),SUM(off_cnt) FROM
(select time,[on] as on_cnt,[off] as off_cnt from table1
pivot
(
count(Status)
for Status in ([on],[off])
) as p) as st
GROUP BY time
Fiddle
How about something like
SELECT
[Time],
SUM(CASE WHEN [Status] = 'On' THEN 1 ELSE 0 END) CntON,
SUM(CASE WHEN [Status] = 'Off' THEN 1 ELSE 0 END) CntOff
FROM Table
GROUP BY [Time]