Crystal Report Time Difference Formula With Conditions - sql-server

I am trying to create a report for labour effectiveness in a manufacturing business that links to 2 x distinct MS SQL databases.
"Database A" contains information about what employees were doing when they were on shift.
"Database B" contains information about what time an employee clocked in or out for payroll info.
One of the comparisons I want to report on, is the total time an employee was logged into a job vs the total time they were clocked in the building. The data is related on employee number. The main report is linked to database A and is grouped on "Employee Name", within the group footer, there is a sub report linked to Database B and the employee name is passed through as a parameter.
My problem is the way database B records clocking in. I am using a SQL command to collect the data:
SELECT
tws.date_and_time
, CONVERT(date, tws.date_and_time) AS 'Date'
,te.first_name
, te.last_name
, concat(te.first_name,' ', te.last_name) AS 'ConcatName'
, CASE WHEN tws.flag IN (1,3) THEN 1 ELSE 0 END as manual_adjustment
, ROW_NUMBER() OVER (PARTITION BY tw.date_and_time ORDER BY tws.date_and_time ASC) AS swipe_number
, ROW_NUMBER() OVER (PARTITION BY tw.date_and_time ORDER BY tws.date_and_time ASC) % 2 AS in_swipe
FROM temployee te
INNER JOIN twork tw
ON te.employee_id = tw.employee_id AND tw.type = 1000
INNER JOIN twork_swipe tws
on tw.work_id = tws.work_id
The "swipe_number" details what number swipe that record is in the time period (e.g. 1st, 2nd, 3rd etc.)
The "in_swipe" displays 1 if this is the employee clocking in or 0 if it employee clocking out.
I am grouping the sub report on date.
This is relatively straight forward if an employee clocks in and out once on the same day, but I am struggling to work out how to account for if an employee clocks in and out multiple times during a shift (for a break for example) or if an employee clocks in on one day and out on another (night shift for example).
I need to sum the total time an employee is clocked in, so I need to evaluate if the 1st clock of the day is an "in swipe", (swipe_number = 1 AND in_swipe = 1) if it is not, it should not be recorded as the difference between swipe_number 2 and 1, it should be from the start of the day (00:00:0000) to swipe_number = 1 as this indicates the employee has been there since midnight.
Likewise if the last (or only) "swipe_number" of the day is an "in swipe", the time should be recorded as between that time and 23:59:5999.
Outside of this, I need to find the time between the date time fields where swipe numbers = 2 & 1, 4 & 3, 6 & 5 etc. (no fixed number of times a swipe can occur).
Can this be handled dynamically in formulas?

Related

LAG and/or LEAD alternative without window function in Pstgresql

Well I'm using Postgresql(but it won't matter if you can advise a solution in any SQL syntax), I have a table like
employee
department
salary
1
sales
30,000
2
sales
25,000
3
marketing
45,000
4
marketing
55,000
so on...
What I want to achieve is:
employee
department
salary
difference
1
sales
30,000
0/null
2
sales
25,000
5,000
3
marketing
45,000
0/null
4
marketing
55,000
10,000
So technically I want to extract the value difference of consecutive rows, however I can't use the window functions (I don't know why, but it is must to avoid in this challenge)
in a perfect world, we'd be able to do lag() or lead() functions partitioned by department name and store the value difference in other column, but I don't know how to do it without them.
I tried subqueries multiple ways, but every time I ended up having NULL or 0 in new a column
You can use a self-join to table itself and join each employee with the previous row within the same department.
SELECT t1.employee, t1.department, t1.salary, ABS(t2.salary - t1.salary) AS difference
FROM tab t1
LEFT JOIN tab t2
ON t1.department = t2.department AND t1.employee = t2.employee +1

Count by days, with all days

I need to count records by days, even if in the day were no records.
Count by days, sure, easy.
But how i can make it to print information, that 'in day 2018-01-10 was 0 records)
Should I use connect by level? Please, any help would be good. Can't use plsql, just oracle sql
First you generate every date that you want in an inline view. I chose every date for the current year because you didn't specify. Then you left outer join on date using whichever date field you have in that table. If you count on a non-null field from the source table then it will count 0 rows on days where there is no join.
select Dates.r, count(tablename.id)
from (select trunc(sysdate,'YYYY') + level - 1 R
from dual
connect by level <= trunc(add_months(sysdate,12),'YYYY') - trunc(sysdate,'YYYY')) Dates
left join tablename
on trunc(tablename.datefield) = Dates.r
group by Dates.r

Need a SQL query to get data from SQL Server database for a given period with certain condition

I have a SQL Server database with a table dbo.sales with 7 columns.
First column contains different sales person names, on column 2 to 6 other information, on column 7, sales average.
Question: what I need is a query to get all sales person details (all seven columns in Excel) if their sales average is more than 60% between a given date.
For example: in my database, I have data from 01/05/2016 to 31/05/2016, if I enter a period in my Excel sheet between 25/05/2016 to 31/05/2016 and my required average for ex. 60% (should be changed as per my need), then I need all the sales person details who continuously have sales average of more than 60% between 25 to 31st May 2016.
If a sales man average was dropped below 60% on 28th May, then I don't want to see him on my report. In simple words, I need all sales person who continuously hitting 60% or more on average sales within my search period.
Not sure if the sales period date is within the table, but if it is, that query should work for you:
;WITH PeriodSales as (
SELECT * FROM Sales
WHERE SalseDate between #StartDt and #EndDt)
SELECT * FROM PeriodSales
WHERE SalesPerson not in (
SELECT SalesPerson FROM PeriodSales
WHERE CASE WHEN IsNumeric(salesavg) = 1
THEN CAST(salesavg as Decimal) ELSE 0 END <= 60.
);

Running concurrent /parallel update statements (T-SQL)

I have a table that is basically records of items, with columns for each day of the month. So basically each row is ITEM , Day1, Day2, Day3, ....I have to run update statements that basically trawl through each row day by day with the current day information requiring some info from the previous day.
Basically, we have required daily quantities. Because the order goes out in boxes (which are a fixed size) and the calculated quantities are in pieces, the system has to calculate the next largest number of boxes. Any "extra quantity" is carried over to the next day to reduce boxes.
For example, for ONE of those records in the table described earlier (the box size is 100)
My current code is basically getting the record, calculate the requirements for that day, increment by one and repeat. I have to do this for each record. It's very inefficient especially since it's being run sequentially for each record.
Is there anyway to parallel-ize this on SQL Server Standard? I'm thinking of something like a buffer where I will submit each row as a job and the system basically manages the resources and runs the query
If the buffer idea is not feasible, is there anyway to 'chunk' these rows and run the chunks in parallel?
Not sure if this helps, but I played around with your data and was able to calculate the figures without row-by-row handling as such. I transposed the figures with unpivot and calculated the values using running total + lag, so this requires SQL Server 2012 or newer:
declare #BOX int = 100
; with C1 as (
SELECT
Day, Quantity
FROM
(SELECT * from Table1 where Type = 'Quantity') T1
UNPIVOT
(Quantity FOR Day IN (Day1, Day2, Day3, Day4)) AS up
),
C2 as (
select Day, Quantity,
sum(ceiling(convert(numeric(5,2), Quantity) / #BOX) * #BOX - Quantity)
over (order by Day asc) % #BOX as Extra
from C1
),
C3 as (
select
Day, Quantity,
Quantity - isnull(Lag(Extra) over (order by Day asc),0) as Required,
Extra
from C2
)
select
Day, Quantity, Required,
ceiling(convert(numeric(5,2), Required) / #BOX) as Boxes, Extra
from C3
Example in SQL Fiddle

MSSQL Comparing rows same table

Hi im looking to compare several rows and check if a certain condition is true/false.
The tables has several columns the ones im interested in are:
Events.Badgeno
Events.Name
Events.Date
Events.Time
Events.Region_id
Events.Data
The region ID can either be 1 or 2.
I want to check weather the same badgeno registers with a different region within a specified date/time difference say 10 mins. (Could be 10 mins before or 10 mins after).
I'm looking to show the records which don't have a record against the 2 regions.
As a further note it should only be within the first and last records of that badge per day.
Normally each record should have a region 1 and 2 record at the start and end. But there maybe multiple region 1's through out the day.
Any suggestions for the best method?
Id Date Time Name Badgeid Region
3385033 27/02/2014 08:16:11 FirstName Surname 5304 2
I think something like this would work
SELECT e.Badgeno,e.Name, e.Date, e.Time,e.Region_id, e.Data
FROM events e
INNER JOIN events e1 ON e1.BadgeNo = e.BadgeNo AND e1.Region_id <> e.RegionId AND DATEDIFF(minutes,e1.date + e1.time,e.date + e.time) > -10 AND DATEDIFF(minutes,e1.date + e1.time,e.date + e.time) < 10
WHERE e1.Region_id IS NULL
you should provide sample data.
This Query is not complete,you can try something with
row_number/rank/dense, partition and check thus number column
generated .
select *,
row_number()over(partition by badgeno,regionno order by badge no)rn from table
where condition of date time

Resources