SQL Server 2008 exec stored procedure on 3rd strike - sql-server

I've been asked to create a process that triggers a stored procedure when an employee hits their 3rd strike. The strikes relate to absence, so if an employee is off 3 times in a 3 month period it hits the trigger.
But... this only applies to single instances of absence, so if a person is off; for example on the 11/01/2016, 12/01/2016 & 13/01/2016 then this is one instance. Meaning I can't do a count on the number of days off sick.
Data I have available and is a fixed process I can't update:
Date | EmpID | EmpName
01/01/2016 | JS01 | John Spartan
02/01/2016 | JS01 | John Spartan
03/01/2016 | JS01 | John Spartan
08/01/2016 | JS01 | John Spartan
19/02/2016 | JS01 | John Spartan
12/02/2016 | JS01 | John Spartan
Based on the above there are more than 2 instances. So this would trigger the procedure
IF EXISTS (<Query Here>)
BEGIN
EXEC usp_ThreeStrikes
END
Is there a way to do this in T-SQL?

If you can't add columns to help query with the task (eg. InstanceID query would group by to find out number of instances), I think best solution would be to create aggregate CLR function for the task.
https://msdn.microsoft.com/en-us/library/ms131056.aspx

You can try the below approach:
Add an additional column to your table to differentiate if the record should be considered for next strike or not (means after 1 instance, it should not be considered the 2nd time)
Create a SQL Update Trigger to call the procedure, based on the below condition:
Get the records whose column is considered for next strike (same column what you have created in first step)
For those particular records check the count if its greater or equal to 3 and call the stored procedure
For those particular records, update the additional column (created in step 1) to not consider it for the subsequent strikes
Hope this helps.

Here you have a query that lists the empid's that were absent three or more times per quarter. You can modify this query in your trigger to only select in the empids/quarters that are present in the inserted table in your trigger.
PS: I've added some random absences to show that the query only selectes when the number of absences is three or more.
CREATE TABLE #absences(dt DATE,empid NVARCHAR(128),empname NVARCHAR(128));
INSERT INTO #absences(dt,empid,empname)VALUES
('20151212','JS02','John Spartan2'),
('20151213','JS02','John Spartan2'),
('20151010','JS01','John Spartan'),
('20151011','JS01','John Spartan'),
('20151217','JS02','John Spartan2'),
('20151219','JS02','John Spartan2'),
('20160101','JS01','John Spartan'),
('20160102','JS01','John Spartan'),
('20160103','JS01','John Spartan'),
('20160108','JS01','John Spartan'),
('20160201','JS02','John Spartan2'),
('20160203','JS02','John Spartan2'),
('20160219','JS01','John Spartan'),
('20160212','JS01','John Spartan');
SELECT
empid,
[quarter]=DATEADD(QUARTER,DATEDIFF(QUARTER,0,o.dt),0)
FROM
#absences AS o
WHERE
NOT EXISTS (
SELECT 1
FROM #absences AS i
WHERE i.empid=o.empid AND
DATEDIFF(QUARTER,0,i.dt)=DATEDIFF(QUARTER,0,o.dt) AND
i.dt=DATEADD(DAY,-1,o.dt)
)
GROUP BY
empid,
DATEDIFF(QUARTER,0,o.dt)
HAVING
COUNT(*)>=3;
DROP TABLE #absences;
Result:
+-------+-------------------------+
| empid | quarter |
+-------+-------------------------+
| JS02 | 2015-10-01 00:00:00.000 |
| JS01 | 2016-01-01 00:00:00.000 |
+-------+-------------------------+

Related

SQL Server - same table for multiple customers

I have a need to manage a dataset for multiple customers - each customer manages a small table to update procedure volumes for the next five years. The table is structured like so:
+-------------+--------+--------+--------+--------+--------+
| | Year 1 | Year 2 | Year 3 | Year 4 | Year 5 |
+-------------+--------+--------+--------+--------+--------+
| Procedure A | 5 | 10 | 14 | 12 | 21 |
+-------------+--------+--------+--------+--------+--------+
| Procedure B | 23 | 23 | 2 | 3 | 4 |
+-------------+--------+--------+--------+--------+--------+
| Procedure C | 5 | 6 | 7 | 8 | 12 |
+-------------+--------+--------+--------+--------+--------+
The values in this table will be managed by each customer via MS PowerApps.
This same structure exists for every single customer. What is the best way to put all of these in one dataset?
Should I just add a column for CUSTOMER ID and just put all the data in there?
The process:
Utilizing PowerApps, a new customer deal will be generated and a row will be added for them in the SQL DB in a customer records table.
Simultaneously, the blank template of the above table should be generated for them.
Now, the customer can interface with this SQL table within PowerApps and add their respective procedure volumes.
The question isn't explained well but:
I would assume all of the customer specific data has at least one column that is the same. For instance CustomerName. You could create your own table with CustomerId, CustomerName, (any other fields you would like to see). If there isn't a concept of CustomerId on the customer's tables, you would have to join them on CustomerName. You could populate your own CustomerId for the new table.
I would be happy to help more if you could clarify the question and show a few examples.

Microsoft SQL create a summary table based on other group of tables

My question is a bit simple, there are many answers to it but I have a question more about the query itself for certain conditions.
I have a table like this :
Client | Date | Employee | Last Record | Trained
JOE | April 2020 | John Doe | May 2019 | TRUE
JOE |February 2020| John Doe | May 2019 | TRUE
JOE | May 2 019 | John Doe | May 2019 | FALSE
Now I watn to make a simple SQL summary table saying :
Client | Date | Inactive | Trained
JOE | April 2020 | 1 | 1
JOE |February 2020 | 1 | 1
JOE | May 2019 | 0 | 0
So basically do a count of Employees grouped by client and date, with the condition that the difference of date and last record is greater than, lets say 1 month and also in another column count the number of employees with a TRUE condition.
So my question is basically that, hwo would I go about creating a summary table where I want to set conditions per column, such as a date difference or if its true in a column.
Before you say Use a view, I need to create this table for performance reason since I am querying the first table which has millions of rows for a report program. However it is simple and better to query instead a table that holds a summary or counts with conditions.

SQL Consecutive Sequence Number gets messed up with ORDER BY

I am working on Windows Form Application and it accesses database in SQL Server 2014. I have EmployeeTable which I retrieve data from, and display all the records in DataGridView. In this table, I have a column SequenceID, which basically increments from 1 up to the number of records in this table, but this is not the same as AUTO INCREMENT in that SequenceID gets updated each time the table is modified, and keeps the numerical order no matter how many times new records get inserted or some records are deleted. For example, if the data looks like
SequenceID | Name
1 | John
2 | Mary
3 | Robert
and Mary is removed, then the resulting table needs to look like
SequenceID | Name
1 | John
2 | Robert
In order to achieve this, I used the best answer by zombat from Update SQL with consecutive numbering, and it was working great until I used ORDER BY expression.
This EmployeeTable also has DateAdded column, containing the date when the record was inserted. I need to display all records ordered by this DateAdded column, with the oldest record shown at the top and the newest at the bottom in addition to the correct SequenceID order. However, it gets messed up when a record is deleted, and a new one is inserted.
If I insert 3 records like,
SequenceID | Name | DateAdded
1 | John | 9/25/2017
2 | Mary | 9/26/2017
3 | Robert | 9/27/2017
and remove Mary, it becomes
SequenceID | Name | DateAdded
1 | John | 9/25/2017
2 | Robert | 9/27/2017
and this is good so far. However, if I add another record Tommy on, say, 9/28/2017, which should be added at the bottom because it is the newest, it results in something like,
SequenceID | Name | DateAdded
1 | John | 9/25/2017
3 | Robert | 9/27/2017
2 | Tommy | 9/28/2017
The ORDER BY is working fine, but it messes up the SequenceID, and I am not sure why this is happening. All I am doing is,
SELECT *
FROM EmployeeTable
ORDER BY DateAdded
I tried placing zombat's SQL command both before and after this SQL command, but neither worked. It seems to me like when I delete a row, the row has an invisible spot, and a new record is inserted in there.
Is there any way to fix this so I can order the records by DateAdded and still have the SequenceID working correctly?
If you need id for GUI (presentation only) you could use:
SELECT ROW_NUMBER() OVER(ORDER BY DateAdded) AS sequenceId, Name, DateAdded
FROM EmployeeTable
ORDER BY DateAdded;
EDIT:
I am trying to update the SequenceID, but it is not getting updated
You should not try to reorder your table every time. It doesn't make sense.

GROUP BY to flatten each group member in a separate column

I am trying to generate a report in SSRS.
I have 2 tables as below:
Address table:
AddressId | AddressLine
AddressCountEachMonth
ID | AddressId | Date | Count
For each date(Year-Month) there is an entry in AddressCountEachMonth table with the count value.
What I would like to do is to be able to query AddressCountEachMonth to output the result as below
For example If I provide a start date: 2014-01-01 and and date: 2014-05-01
Query result should be:
Address | 2016-01 | 2016-02 | 2016-03 | 2016-04 | 2016-05|
x 5 1 0 2 4
y 2 3 4 0 2
...
...
is there any function in SQL Server that would help? I looked into STUFF but could not generate the result.
Luckily SSRS provides the ability to pivot dynamically so you will not have to hard code a query or build dynamic sql. Check out this article that shows step by step how to do this.
https://msdn.microsoft.com/en-us/library/ms157334%28v=sql.100%29.aspx?f=255&MSPPError=-2147217396
Another good one:
https://www.simple-talk.com/sql/reporting-services/advanced-matrix-reporting-techniques/

select all rows that have more than one ID in a specific date

My table:
Items | Price | UpdateAt
1 | 2000 | 02/02/2015
2 | 4000 | 06/04/2015
3 | 2150 | 07/05/2015
4 | 1800 | 07/05/2015
5 | 5540 | 08/16/2015
4 | 1700 | 12/24/2015
5 | 5200 | 12/26/2015
2 | 3900 | 01/01/2016
4 | 2000 | 06/14/2016
As you can see, this is a table that keeps items' price as well as their old price before the last update.
Now I need to find the rows which :
UpdateAt is more than 1 year ago from now
Must have updated price at least once ever since
Aren't the most up-to-date price
So with those conditions, the result from the above table should be :
Items | Price | UpdateAt
2 | 4000 | 06/04/2015
4 | 1800 | 07/05/2015
I can achieve what I need with this
Declare #LastUpdate date set #LastUpdate = DATEADD(YEAER, -1, GETDATE())
select Items, UpdateAt from ITEM_PRICE where Items in (
select Items from (
select Items, count(Items) as C from ITEM_PRICE group by Items) T
where T.C > 1)
and UpdateAt < #LastUpdate
But since I am still a newbie in sqlserver, and this need to be done in vb.net, passing along that query with lots of select in it seems sloppy and hard to maintain.
So, I would like to ask if anyone can give me a simpler solution ?
Sorry, i edited my question as I need one more condition to be met after trying #Tim Biegeleisen's answer, which is indeed the correct one for the question before edit. And I can't figure this out anymore.
Why I need all those condition, it's because I'm having to clean up the table: Clearing off the data that's older than 1 year, while still keeping the most up-to-date item price.
In my answer below, I use a subquery to identify all items which appear in the table during the last year. This is the requirement of having an updated price "at least once ever since." In the outer query, I restrict to only records which are older than one year from now, which is the other part of the requirement. An INNER JOIN is used, because we want to filter off records which do not meet both criteria.
SELECT t1.Items, t1.Price, t1.UpdateAt
FROM ITEM_PRICE t1
INNER JOIN
(
SELECT DISTINCT Items
FROM ITEM_PRICE
WHERE UpdateAt > DATEADD(year, -1, GETDATE())
) t2
ON t1.Items = t2.Items
WHERE t1.UpdateAt <= DATEADD(year, -1, GETDATE())
Once again, SQL Fiddle is having problems simulating SQL Server. But I went ahead and created a Fiddle in MySQL, which looks nearly identical to my SQL Server answer. You can verify that the logic and output are correct.
SQLFiddle

Resources