Hi and thanks in advance for your help
I am struggling to write a stored procedure in sql server to manipulate some records which are batch imported from a csv file without any particular order.
Each record represents an appointment: an entry datetime, an exit datetime and an operator ID to keep track of who did each appointment. Every appointment is 1hr in duration maximum, so moving records ahead sequentially by one hour will do the trick, I just need to have 0 overlapping minutes.
Primary ID
Entry
Exit
Operator ID
1
01/02/2000 07:00:00
01/02/2000 07:45:00
750
2
02/02/2000 07:00:00
02/02/2000 07:45:00
751
3
01/02/2000 07:00:00
01/02/2000 07:45:00
750
4
01/02/2000 07:00:00
01/02/2000 07:45:00
752
5
02/02/2000 07:00:00
02/02/2000 07:45:00
751
6
02/02/2000 07:00:00
02/02/2000 07:45:00
751
7
01/02/2000 07:00:00
01/02/2000 07:45:00
750
My problem is that when imported all appointments are all fixed at 7.00am and I can't change that.
What I am trying to achieve is to shift by one hour overlapping dates for each operator, like this:
Primary ID
Entry
Exit
Operator ID
2
02/02/2000 07:00:00
02/02/2000 07:45:00
751
5
02/02/2000 08:00:00
02/02/2000 08:45:00
751
6
02/02/2000 09:00:00
02/02/2000 09:45:00
751
Of course I have to do this check for each operator, most importantly without jamming the server with these queries.
What must not change is the duration of the appointment (exit - entry), so that I can feed this data to another stored procedure I have already in use that will count the miinutes worked for every operator.
I look forward to reading any idea that might help me get out of this dead end.
Thank you
So if we ignore the issue of more than 17 (24 - 7) appointments for a given operator in a given date, we can use something like:
with cte as (
select *,
cast(entrytm as date) as entrydate,
row_number() over (partition by operatorid, cast(entrytm as date) order by primaryid) as rno
from load)
select *, dateadd(hour, (rno - 1), entrytm) as newtm
from cte
order by operatorid, entrydate, rno
;
The fiddle code is a bit messy since I simply adapted a script that I often use as a starting point. Notice that I both pruned your sample data and added some additional rows for a better test. YOU should take that responsibility when posting a question by providing consumable data as that will encourage others to help.
fiddle to demonstrate. The tally table is not needed in this case but the concept has many uses and is good to understand and learn.
Related
I am working on a query to calculate the time since the latest preventative maintenance (PM) for each piece of equipment on a rolling calendar. The goal is build a dataframe to analyze when a repair will take place.
Below is a table of the query results that I have with the added column "Time Since Last PM" which is the column that I want.
Call this Table 1:
EquipmentNumber |Year |weeknumber |Current Week Repair|Time Since Last PM
2069186 |2018 |10 |1 |5
2069186 |2018 |21 |1 |1
1626930 |2018 |09 |1 |21
1626930 |2019 |03 |1 |15
The preventative maintenance data comes from a query/table that is set up like the following i.e. Table 2.
Equipment Number |Year |WeekNumber
2069186 |2018 |5
2069186 |2018 |20
1626930 |2017 |40
1626930 |2018 |40
So I need to make sure that for my final query, Table 1, the “Time Since Last PM” for equipment 2069186 the first record is difference from week 5 2018 in Table 2 to week 10 2018. For the second record of equipment 2069186 the “Time Since Last PM” should be the difference between week 21 2018 in Table 1 and week 20 2018 in Table 2. For equipment 1626930 the first record should be the difference from week 9 2018 in Table 1 to week 40 2017 in Table 2. For equipment 1626930 the second record should be the difference from week 3 2019 in Table 1 to week 40 2018 in Table 2. Keep in mind that I want the difference between the current record in Table 1 and the latest PM prior to the year and week in Table 1.
The queries for Table 1 and Table 2 are very basic.
SELECT
DISTINCT EquipmentNumber,
Year,
weeknumber,
[Current Week Repair]
FROM TableA
SELECT
EquipmentNumber,
DatePart(Year, Created) as Year,
DatePart(Week, Created) as WeekNumber
FROM TableB
Any suggestions on the proper way to join the two tables and make the calculation? Or is there a way to utilize temp tables and variables that anyone can suggest? Any input would be appreciated!
You can use APPLY:
SELECT t1.*, t1.WeekNumber - ca.WeekNumber
FROM t1
OUTER APPLY (
SELECT TOP 1 Year, WeekNumber
FROM t2
WHERE Equipment_Number = t1.Equipment_Number
AND (
(Year < t1.Year)
OR
(Year = t1.Year AND WeekNumber < t1.WeekNumber)
)
ORDER BY Year DESC, WeekNumber DESC
) AS ca
Calculating week number difference will be tricky and for that you'll need the number of weeks in the previous year.
This is something I am not getting for some or other reason.
I have a list of records
BusinessUnitId Position Date Time
-----------------------------------------------------------
76 Staff 3/30/2009 11:00:00 AM
76 Staff 3/30/2009 04:00:00 PM
76 Management 3/30/2009 05:00:00 PM
78 Exco 3/30/2009 09:00:00 AM
78 Staff 3/30/2009 09:30:00 AM
If I do a group by
select
count(answer.BusinessUnitId)
from
AnswerSelected answer
group by
answer.BusinessUnitId
I retrieve a value of 3 and 2
What I am trying to achieve is get a count of 2
So in total 2 business units submitted answers, 76 and 78(hope this makes sense)
How can I do this?
Thanks
Use COUNT(DISTINCT ...)
SELECT
COUNT(DISTINCT BusinessUnitId)
FROM AnswerSelected
You don't need to use GROUP BY in this particular case to get the distinct count of business units across your entire table.
Demo here:
Rextester
I have a requirement to write a Informix Query that will fetch all the records of the table excluding Friday and Saturday of all the weeks and data between 4PM to 8PM of all the days of the week
Ex:
If I have the following records in my table
Name ProcessStartTime Status
Name1 2017-04-01 17:00:02.000 SUCCESS(Saturday)
Name2 2017-04-02 21:00:02.000 SUCCESS(Sunday)
Name3 2017-04-03 01:00:02.000 SUCCESS(Monday)
Name4 2017-04-04 05:00:02.000 SUCCESS(Tuesday)
Name5 2017-04-05 18:00:02.000 SUCCESS(Wednesday)
Name6 2017-04-05 15:00:02.000 SUCCESS(Wednesday)
Name7 2017-04-06 23:00:02.000 SUCCESS(Thursday)
Name8 2017-04-07 15:00:02.000 SUCCESS(Friday)
If I execute the Query I should get the Following records only,
Name2 2017-04-02 21:00:02.000 SUCCESS(Sunday)
Name3 2017-04-03 01:00:02.000 SUCCESS(Monday)
Name4 2017-04-04 05:00:02.000 SUCCESS(Tuesday)
Name6 2017-04-05 15:00:02.000 SUCCESS(Wednesday)
Name6 2017-04-06 23:00:02.000 SUCCESS(Thursday)
And the remaining data should not fetched because, those records are either Friday or Saturday as well as date time between 4PM to 8PM(Not only Friday and Saturday but for all the days of the week).
I have my SQL Server query here below which is working fine in SSMS,
SET DATEFIRST 1
SELECT Name, ProcessStartTime, Status
FROM #events
WHERE datepart(DW, ProcessStartTime) NOT IN (5,6)
AND (datepart(hh, ProcessStartTime) < 16
OR
ProcessStartTime > DATEADD(dd, DATEDIFF(dd, 0, ProcessStartTime), '08:00:00'))
GO
but I need to change this Query into Informix Query. I Googled a lot to find the way to get the one but nothing worked. Could anyone please help me on this?
Using this WHERE clause for the query should work:
WHERE WEEKDAY(ProcessStartTime) NOT IN (5,6)
AND EXTEND(ProcessStartTime, HOUR TO HOUR)::char(2)::int
NOT BETWEEN 16 AND 20
A double cast is necessary as there is no builtin cast operation from datetime to integer.
This is similar to Simon Riddle's answer, but uses an explicit time range notation:
SELECT Name, ProcessStartTime, Status
FROM Events
WHERE WEEKDAY(ProcessStartTime) NOT IN (5, 6)
AND (EXTEND(ProcessStartTime, HOUR TO SECOND) < DATETIME(16:00:00) HOUR TO SECOND
OR EXTEND(ProcessStartTime, HOUR TO SECOND) >= DATETIME(20:00:00) HOUR TO SECOND
)
I prefer this because I think it is easier to tweak it to include/exclude the exact ends of the date ranges that you want. I think the notation is probably what you want; the >= might need to be > if events at exactly 8 pm should be included rather than excluded. Note that the BETWEEN…AND operators include both the end points in the range.
I am trying to figure out how to apply a unique constraint based on weeks in a quarter.
I have a table that includes Quarter (1Q2014, 2Q2014, ...) as well as an Effective Date and an Expiration date.
I need to allow multiple records for the same Qtr as long as Effective and Expiration Dates do not overlap.
For example, these records would be legitimate:
Qtr EffDte ExpDte
--------------------------------------
1Q2014 2014-01-06 2014-02-03
1Q2014 2014-02-10 2014-02-24
1Q2014 2014-03-03 2014-03-17
While these records would not be legitimate:
Qtr EffDte ExpDte
--------------------------------------
1Q2014 2014-01-06 2014-03-24
1Q2014 2014-02-10 2014-03-10
1Q2014 2014-03-03 2014-03-17
I am not sure if I need to alter my table design to achieve this goal.
Does anyone have any suggestions?
This one is tricky for me, can't figure it out.
We have a system where we calculate inventory numbers on the fly. If there's a month where a customer doesn't have any orders, there's no record for that month but the beginning inventory is still calculated and displayed as a rolling calculation based on the previous transaction data.
I'm now pulling this data but need to "fill in the blanks" so to speak.
For example, the table has the following fields:
MonthYear DATETIME
WarehouseID INT
Quantity DECIMAL(18,2)
If I put all this in a temporary table to do calculations, I'll end up with something like this:
2010-01-01 00:00:00.000 135 1000.00
2010-04-01 00:00:00.000 135 2000.00
2010-07-01 00:00:00.000 135 3000.00
2010-06-01 00:00:00.000 235 1000.00
2010-07-01 00:00:00.000 235 2000.00
2011-02-01 00:00:00.000 135 1000.00
2011-03-01 00:00:00.000 135 2450.00
etc., etc.
What I need to do is for each warehouse, if a record exists for that year, add a blank row for any months that aren't in the table.
In the example above for warehouse 135 I need to add a record for 02, 03, 05, 08, etc.
Is there any easier way of doing this rather than with cursors and loops?
Thanks.
Search Recursive CTE. Then LEFT JOIN. Gotta bolt out the door. Sorry for quick answer.