ORACLE SQL - (SYSDATE-1) ignoring weekend - sql

I am relatively new to SQL and need to construct a small productivity query to retrieve results from the day prior (in this case, time of the first and last picking transaction, and then a count of total picks).
The issue is that obviously on Monday when this query runs, it returns no results and as such we never get the friday results. I would therefore like to know how to ignore the weekend days.
This is my query as of now:
SELECT EMPLOYEE_ID, MIN(END_TRAN_TIME), MAX(END_TRAN_TIME), COUNT(TRAN_TYPE)
FROM T_TRAN_LOG
WHERE WH_ID ='W376' AND TRUNC(END_TRAN_DATE) = TRUNC(sysdate-1) AND TRAN_TYPE IN ('301', '303', '305')
GROUP BY EMPLOYEE_ID;
Any help is greatly appreciated!

To ignore the weekend days, you can modify the query to check if the day of the week is not a weekend day (Saturday or Sunday).
SELECT EMPLOYEE_ID, MIN(END_TRAN_TIME), MAX(END_TRAN_TIME), COUNT(TRAN_TYPE)
FROM T_TRAN_LOG
WHERE WH_ID ='W376' AND
TRUNC(END_TRAN_DATE) = TRUNC(sysdate-1) AND
TRAN_TYPE IN ('301', '303', '305') AND
TO_CHAR(END_TRAN_DATE, 'DAY') NOT IN ('SATURDAY', 'SUNDAY')
GROUP BY EMPLOYEE_ID;
Hope this helps

Related

Trouble comparing to_char(timestamp, 'day') = 'monday'

In a PostgreSQL database, I've got a table payment with a column payment_date of type timestamp. My goal is to count payments made on Monday. The following query:
SELECT TO_CHAR(payment_date, 'day') FROM payment;
gives result such as:
thursday
friday
friday
monday
tuesday
However when I try to count Mondays like this:
SELECT COUNT(*) FROM payment
WHERE TO_CHAR(payment_date, 'day') = 'monday';
the result is 0 even though the previous query shows it should be greater than 0.
What's wrong about the second query?
Postgres docs says that "full lower case day name (blank-padded to 9 chars)"
May this select solve the problem? If there are trailing spaces, maybe your comparison fails.
SELECT COUNT(*)
FROM payment
WHERE RTRIM(TO_CHAR(payment_date, 'day')) = 'monday';

Counting working days between two dates Oracle

I'm trying to write a query which can count the number of working days between a payment being received and being processed, I started playing around with this for payments received in December 2017;
select unique trunc(date_received),
(case when trunc(date_received) in ('25-DEC-17','26-DEC-17') Then 0 when
to_char(date_received,'D') <6 Then 1 else 0 end) Working_day
from payments
where date_received between '01-DEC-17' and '31-dec-17'
order by trunc(date_received)
But to be honest, I'm at a loss as to how to take it further and add in date_processed and count the number of working days between date_processed and date_received... Any help would be much appreciated...
Maybe not the most optimal, but it works quite nicely, and it's easy to incorporate more complicated checks, like holidays. This query first generates all dates between the two dates, and then lets you filter out all the days that 'don't count'.
In this implementation I filtered out only weekend days, but it's quite easy to add checks for holidays and such.
with
-- YourQuery: I used a stub, but you can use your actual query here, which
-- returns a from date and to date. If you have multiple rows, you can also
-- output some id here, which can be used for grouping in the last step.
YourQuery as
(
select
trunc(sysdate - 7) as FromDate,
trunc(sysdate) as ToDate
from dual),
-- DaysBetween. This returns all the dates from the start date up to and
-- including the end date.
DaysBetween as
(
select
FromDate,
FromDate + level - 1 as DayBetween,
ToDate
from
YourQuery
connect by
FromDate + level - 1 <= ToDate)
-- As a last step, you can filter out all the days you want.
-- This default query only filters out Saturdays and Sundays, but you
-- could add a 'not exists' check that checks against a table with known
-- holidays.
select
count(*)
from
DaysBetween d
where
trim(to_char(DAYINBETWEEN, 'DAY', 'NLS_DATE_LANGUAGE=AMERICAN'))
not in ('SATURDAY', 'SUNDAY');

Sum of shifting range in SQL Query

I am trying to write an efficient query to get the sum of the previous 7 days worth of values from a relational DB table, and record each total against the final date in the 7 day period (e.g. the 'WeeklyTotals Table' in the example below). For example, in my WeeklyTotals query, I would like the value for February 15th to be 333, since that is the total sum of users from Feb 9th - Feb 15th, and so on:
I have a base query which gets me my previous weeks users for today's date (simplified for the sake of the example):
SELECT Date, Sum("Total Users")
FROM "UserRecords"
WHERE (dateadd(hour, -8, "UserRecords"."Date") BETWEEN
dateadd(hour, -8, sysdate) - INTERVAL '7 DAY' AND dateadd(hour, -8, sysdate);
The problem is, this only get's me the total for today's date. I need a query which will get me this information for the previous seven days.
I know I can make a view for each date (since I only need the previous seven entries) and join them all together, but that seems really inefficient (I'll have to create/update 7 views, and then do all the inner join operations). I am wondering if there's a more efficient way to achieve this.
Provided there are no gaps, you can use a running total with SUM OVER including the six previous rows. Use ROW_NUMBER to exclude the first six records, as their totals don't represent complete weeks.
select log_date, week_total
from
(
select
log_date,
sum(total_users) over (order by log_date rows 6 preceding) as week_total,
row_number() over (order by log_date) as rn
from mytable
where log_date > 0
)
where rn >= 7
order by log_date;
UPDATE: In case there are gaps, it should be
sum(total_users) over (order by log_date range interval '6' day preceding)
but I don't know whether PostgreSQL supports this already. (Moreover the ROW_NUMBER exclusion wouldn't work then and would have to be replaced by something else.)
Here's a a query that self joins to the previous 6 days and sums the value to get the weekly totals:
select u1.date, sum(u2.total_users) as weekly_users
from UserRecords u1
join UserRecords u2
on u1.date - u2.date < 7
and u1.date >= u2.date
group by u1.date
order by u1.date
You can use the SUM over Window function, with the expression using Date Part, of week.
Self joins are much slower than Window functions.

sql to find the weekdays in the month from the current day

please help me with this. using SQL server 2008
I need to find the number of sales done on the current day.
then find the weekday from current date and based on that find the average of the sales on all those particular weekdays in the last month
ex:
select count(sales) from salestable where orderdate= getdate()
where it gives the count of the sales done on the current date
then I need to find out the average of the sales done on the same weekday for ex if today is Sunday find the average of the sales done in the last month on all Sundays in that month.
I recommend that you borrow the data warehousing technique of creating a Calendar table that you pre-populate with 1 row for every date within the range you might need. You can add to it basically any column that is useful - in this case DayOfWeek and MonthID. Then you can eliminate date math entirely and use joins - sort of like this (not complete but points you in the right direction):
select count(salestable.sales) as salescount, a.salesavg
from salestable
join calendar on salestable.orderdate = calendar.calendardate
join (
select monthid, dayofweek, avg(salestable.sales) as salesavg
from salestable
join calendar on salestable.orderdate = calendar.calendardate
group by monthid, dayofweek) as a
on calendar.monthid = a.monthid and calendar.dayofweek = a.dayofweek
where calendar.calendardate = getdate()
You create and populate the calendar table once and reuse it every time you need to do date operations. Once you get used to this technique, you will NEVER go back to date math.
For this kind of queries are Common Table Expressions very usefull. Then you can use DATEPART function to get day of week.
This solution is also untested and intended to just point you in the right direction.
This solution uses a co-related sub-query to get the average sales.
select
order_date,
count(sales) total_sales,
(select avg(sales)
from sales_table
where order_date between dateadd(day,-30,#your_date) and #your_date
and datepart(WEEKDAY,order_date) = datepart(WEEKDAY,#your_date)
) avg_sales_mth
from sales_table
where order_date = #your_date

Sql daily comparison by month

I am writing a report for work which requires that I compare the amount of students dropped on a daily basis, what I mean is the report needs to show that on today the 5th of august X amounts of students dropped from the 1st to the 5th compared to X amount which dropped within the 1st to the 5th of July and so on for each Month of the year. Can anyone please help me by providing me with a query which I can use to have that info? thanks.
You want to compare the first number of days from a month. The following query gives you an example:
select yr, mon, count(*)
from (select extract(year from date) as yr, extract(month from date) as mon,
extract(day from date) as day
from t
) t
where day <= extract(day from now())
group by yr, mon
However, the exact syntax may depend on your database. For instance, the current date may be now(), getdate(), system_date or something else. Some databases don't support the extract, but most have a way to get the month and day of month.