Create Stored procedure for setting reminder for document created - sql

I want to create a Stored procedure for the
documents whose NStatusFlag should not be equal to 5 and 14
AND
also it should send Reminder to the respective user if the Document is with them for more than 3 days and if it is for more than 5 days then it should send it to its senior also
The date should be calculated with the U_datetime of the table and with the SYSTEM date from the system.
My NStatusFlag suggest which all documents are opened.
I tried below.
ALTER PROCEDURE GET_INWARD_REMINDER_REPORT
AS
BEGIN
Select * from inward_doc_tracking_trl
where NStatus_flag <> 5
and NStatus_flag <> 14
END
GO
SO I got all the documents which are opened, like below
But I am stuck how to get the all user by comparing with the date and send the reminders.
Also, I will get the Name of the USer with which the document is assigned from the inward_doc_tracking_hdr table.
NOTE inward_doc_tracking_hdr table mkey is related to ref_mkey from the inward_doc_tracking_trl table.
kindly help me out.
UPDATE
I get all the User from this query
ALTER PROCEDURE GET_INWARD_REMINDER_REPORT
AS
BEGIN
Select distinct a.mkey, b.mkey, a.first_name + ' ' + a.last_name from user_mst a
inner join inward_doc_tracking_hdr b
on a.mkey = b.User_Id
END
GO
UPDATE to get SEnior name
select * from inward_doc_tracking_hdr order by mkey desc -- here I get To_User
select * from user_mst where mkey = 187 -- here I get To_User
select Reporting_To,* from emp_mst where mkey = 122 -- here I get Senior

This query gets the tracking lines of people with documents for 3 days or more (you might need to be careful with the time component). Please test and see if this gets what you want.
Select TL.*
from inward_doc_tracking_trl TL
where TL.NStatus_flag NOT IN (5,14)
and TL.U_datetime <= DATEADD(d, -3, GETDATE())
This query then works out if its 3 or 5 days overdue and populates a second column if it's 3 days overdue:
Select
TL.*,
U.UserName,
CASE
WHEN TL.U_datetime <= DATEADD(d, -5, GETDATE())
THEN M.Reporting_To
ELSE NULL
END SeniorName
from inward_doc_tracking_trl TL
INNER JOIN inward_doc_tracking_hdr TH
ON TH.mkey = TL.ref_mkey
INNER JOIN user_mst U
ON TH.User_Id = U.mkey
INNER JOIN emp_mst M
ON M.mkey = U.employee_mkey
where TL.NStatus_flag NOT IN (5,14)
and TL.U_datetime <= DATEADD(d, -3, GETDATE())
You need to run that every day, I suggest inside a scheduled SQL Agent Job
With regards to 'sending a reminder', then assuming this is email, I suggest you first set up SQL Mail: https://msdn.microsoft.com/en-au/library/hh245116.aspx
Then use sp_send_dbmail https://msdn.microsoft.com/en-au/library/ms190307.aspx to send the email message
You'll also need to use the above query in a cursor and feed that into your sp_send_dbmail How to send multiple emails from sql server database using sp_send_dbmail procedure
Have a crack at that and ask more questions if you like

Related

daily incremental results on table where transaction date <= #Date parameter

specifically looking for General Leger results. This means that I can't sum up transactions for specfic dates, or cant run Between date.
to get the results for say, today I would need to query the table for all transactions <= #Today.
That said, i am tasked with running this for every single day in 2020 thus far. is there a method to do this where i dont have to manually run for each day myself?
Query example:
glo.GLValue
, Sum(UnitCR) AS 'Credit'
, Sum(UnitDR) AS 'Debit'
, sum(FirmCR) AS 'FirmCredit'
, sum(FirmDR) AS 'FirmDebit'
FROM glacct ga
inner join gldetail gd on gd.glacct = ga.AcctIndex
inner join glnatural gn on ga.glnatural = gn.GLNaturalID
inner join glunit glu on ga.glunit = glu.GLUnitID
inner join gloffice glo on ga.GLOffice = glo.GLOfficeID
WHERE gn.GLNat IN ('11001','11002','11003','11005','11007','11011','11016','11019','11020','11021','11022','11024','11025','11026','11027','11032','11033',
'11034','11035','11036','11037','11040','11041','11042','11043','11044','11050','11051','11052','11053','11190','11199','11201','11202','11203','11204',
'11205','11206','11207','11301','11603','11700','11705','11801','11802','11803','11804','11806','11807','11808','11809','11901')--,'22001')
AND gd.PostDate <= #Yesterday
GROUP BY
glo.GLValue
Create a sub-table that give the sums for each PostDate and GLValue similar to above but also grouped on PostDate, then join that to your select above, e.g.
inner join gloffice glo on ga.GLOffice = glo.GLOfficeID
inner join ( ... new grouped select here ...) gs on gs.GLValue = glo.GlValue and gs.PostDate < gd.PostDate
Now you should be able to sum the gs values:
, Sum(gs.Credit) as Credit
, Sum(gs.Debit) as Debit
etc.

Query to update subscriber status to a list in salesforce marketing cloud

I have a data extension that I will be populating my subscriber information into (I have to do this due to my API set up). However, I want this information to be pasted to my publication list in salesforce. If people unsubscribe, a field in my data extension called 'Subscribed' will be updated to 'False' (and vica-versa). I want to set up a query to run everday that scans this data extension and updates all the false records to unsubscibed in my publication list. I built the query below, but I am getting an error that say
"Incorrect syntax near the keyword 'INNER'."
SELECT b.EMAIL_ADDRESS, 'Unsubscribed' AS Status
FROM Welcome b
WHERE b.Subscribed = 'False'
AND Date_Changed >= DATEADD(day, -1, GETDATE())
INNER JOIN _ListSubscribers a
ON a.EmailAddress = b.EMAIL_ADDRESS
WHERE a.ListID = '112'
Thanks!
Where clause always goes after joins
SELECT b.EMAIL_ADDRESS, 'Unsubscribed' AS Status
FROM Welcome b
INNER JOIN _ListSubscribers a ON a.EmailAddress = b.EMAIL_ADDRESS
WHERE b.Subscribed = 'False' and
a.ListID = '112' and
b.Date_Changed >= DATEADD(day, -1, GETDATE());

Iteration between 2 tables SQL Query

Im very new using SQL as you can see and i got a doubt about the iteration using 2 tables.
Here is the thing:
I have two tables "UsersEmails" and "Sent_Emails".
In the "UsersEmail" i have all the emails (user accounts) and in the "Sent_Emails" i have the emails sent during one period of time for example "TODAY".
So, i'd like to KNOW which email account on my "UsersEmail" table where sent TODAY and which ones werent.
I got an idea by iterating every email in my table "UsersEmail" and checking it on the table "Email_Sent" but i dont know how to do it.
I hope you guys could help me with this.
My best regards.
You gave little information about your tables however supposedly you can write this:
sent today:
select * from UsersEmail e
where exists (select 1 from Sent_Emails where userEmailID=e.ID and
TRUNC(emailDate)=TRUNC(sysdate))
not sent today:
select * from UsersEmail e
where not exists (select 1 from Sent_Emails where userEmailID=e.ID and
TRUNC(emailDate)=TRUNC(sysdate))
you actually want to track the mails sent and cannot be sent?
if i were you, i'd add a column to my table "Sent_Emails" datetime, and set send date when i mail is sent by a user,
and in that case ,
--MAILS SENT: SELECT * FROM SEND_MAILS WITH (NOLOCK) INNER JOIN USEREMAILS WITH (NOLOCK) ON SEND_MAILS.USERMAILID =
USEREMAILS.USERMAILID WHERE SEND_MAILS.SENDDATE IS NOT NULL
--MAILS NOT - SENT: SELECT * FROM SEND_MAILS WITH (NOLOCK) INNER JOIN USEREMAILS WITH (NOLOCK) ON SEND_MAILS.USERMAILID =
USEREMAILS.USERMAILID WHERE SEND_MAILS.SENDDATE IS NULL
And with this info, you can report mails-sent on daily base.
like
SELECT * FROM SEND_MAILS WITH (NOLOCK) INNER JOIN USEREMAILS WITH
(NOLOCK) ON SEND_MAILS.USERMAILID = USEREMAILS.USERMAILID WHERE
SEND_MAILS.SENDDATE = '2016-05-24'
Emails Sent today
SELECT * FROM UserEmail as E
INNER JOIN sentEmails AS s ON s.userEmailID = e.UserEmailId
WHERE s.date = YOUR_TARGET_DATE
Emails not sent today
SELECT * FROM UserEmail as E
INNER JOIN sentEmails AS s ON s.userEmailID = e.UserEmailId
WHERE s.date <> YOUR_TARGET_DATE
I like to repeat the problem to myself in English and then write the SQL. You want to compare the last email sent for a given userEmailID to the start of today. The subquery below gives you the last email sent for a given userEmailID. The case statement will be 1 for sent today and 0 for never sent or last email sent earlier than today.
SELECT E.*,
CASE WHEN MaxSentEmail > trunc_date(getdate()) THEN 1 ELSE 0 END AS SentToday
FROM UserEmail as E
LEFT JOIN (SELECT se.userEmailID,
max(se.sentEmails) AS MaxSentEmail
FROM sentEmails se
GROUP BY se.userEmailID) as se
on E.UserEmailID = se.userEmailID
ORDER BY E.UserEmailID

Compare values from one table with the results from a query?

First, I will explain the what is being captured. User's have a member level associated with their accounts (Bronze, Gold, Diamond, etc). A nightly job needs to run to calculate the orders from today a year back. If the order total for a given user goes over or under a certain amount their level is upgraded or downgraded. The table where the level information is stored will not change much, but the minimum and maximum amount thresholds may over time. This is what the table looks like:
CREATE TABLE [dbo].[MemberAdvantageLevels] (
[Id] int NOT NULL IDENTITY(1,1) ,
[Name] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[MinAmount] int NOT NULL ,
[MaxAmount] int NOT NULL ,
CONSTRAINT [PK__MemberAd__3214EC070D9DF1C7] PRIMARY KEY ([Id])
)
ON [PRIMARY]
GO
I wrote a query that will group the orders by user for the year to date. The query includes their current member level.
SELECT
Sum(dbo.tbh_Orders.SubTotal) AS OrderTotals,
Count(dbo.UserProfile.UserId) AS UserOrders,
dbo.UserProfile.UserId,
dbo.UserProfile.UserName,
dbo.UserProfile.Email,
dbo.MemberAdvantageLevels.Name,
dbo.MemberAdvantageLevels.MinAmount,
dbo.MemberAdvantageLevels.MaxAmount,
dbo.UserMemberAdvantageLevels.LevelAchievmentDate,
dbo.UserMemberAdvantageLevels.LevelAchiementAmount,
dbo.UserMemberAdvantageLevels.IsCurrent as IsCurrentLevel,
dbo.MemberAdvantageLevels.Id as MemberLevelId,
FROM
dbo.tbh_Orders
INNER JOIN dbo.tbh_OrderStatuses ON dbo.tbh_Orders.StatusID = dbo.tbh_OrderStatuses.OrderStatusID
INNER JOIN dbo.UserProfile ON dbo.tbh_Orders.CustomerID = dbo.UserProfile.UserId
INNER JOIN dbo.UserMemberAdvantageLevels ON dbo.UserProfile.UserId = dbo.UserMemberAdvantageLevels.UserId
INNER JOIN dbo.MemberAdvantageLevels ON dbo.UserMemberAdvantageLevels.MemberAdvantageLevelId = dbo.MemberAdvantageLevels.Id
WHERE
dbo.tbh_OrderStatuses.OrderStatusID = 4 AND
(dbo.tbh_Orders.AddedDate BETWEEN dateadd(year,-1,getdate()) AND GETDATE()) and IsCurrent = 1
GROUP BY
dbo.UserProfile.UserId,
dbo.UserProfile.UserName,
dbo.UserProfile.Email,
dbo.MemberAdvantageLevels.Name,
dbo.MemberAdvantageLevels.MinAmount,
dbo.MemberAdvantageLevels.MaxAmount,
dbo.UserMemberAdvantageLevels.LevelAchievmentDate,
dbo.UserMemberAdvantageLevels.LevelAchiementAmount,
dbo.UserMemberAdvantageLevels.IsCurrent,
dbo.MemberAdvantageLevels.Id
So, I need to check the OrdersTotal and if it exceeds the current level threshold, I then need to find the Level that fits their current order total and create a new record with their new level.
So for example, lets say jon#doe.com currently is at bronze. The MinAmount for bronze is 0 and the MaxAmount is 999. Currently his Orders for the year are at $2500. I need to find the level that $2500 fits within and upgrade his account. I also need to check their LevelAchievmentDate and if it is outside of the current year we may need to demote the user if there has been no activity.
I was thinking I could create a temp table that holds the results of all levels and then somehow create a CASE statement in the query above to determine the new level. I don't know if that is possible. Or, is it better to iterate over my order results and perform additional queries? If I use the iteration pattern I know i can use the When statement to iterate over the rows.
Update
I updated my Query A bit and so far came up with this, but I may need more information than just the ID from the SubQuery
Select * into #memLevels from MemberAdvantageLevels
SELECT
Sum(dbo.tbh_Orders.SubTotal) AS OrderTotals,
Count(dbo.AZProfile.UserId) AS UserOrders,
dbo.AZProfile.UserId,
dbo.AZProfile.UserName,
dbo.AZProfile.Email,
dbo.MemberAdvantageLevels.Name,
dbo.MemberAdvantageLevels.MinAmount,
dbo.MemberAdvantageLevels.MaxAmount,
dbo.UserMemberAdvantageLevels.LevelAchievmentDate,
dbo.UserMemberAdvantageLevels.LevelAchiementAmount,
dbo.UserMemberAdvantageLevels.IsCurrent as IsCurrentLevel,
dbo.MemberAdvantageLevels.Id as MemberLevelId,
(Select Id from #memLevels where Sum(dbo.tbh_Orders.SubTotal) >= #memLevels.MinAmount and Sum(dbo.tbh_Orders.SubTotal) <= #memLevels.MaxAmount) as NewLevelId
FROM
dbo.tbh_Orders
INNER JOIN dbo.tbh_OrderStatuses ON dbo.tbh_Orders.StatusID = dbo.tbh_OrderStatuses.OrderStatusID
INNER JOIN dbo.AZProfile ON dbo.tbh_Orders.CustomerID = dbo.AZProfile.UserId
INNER JOIN dbo.UserMemberAdvantageLevels ON dbo.AZProfile.UserId = dbo.UserMemberAdvantageLevels.UserId
INNER JOIN dbo.MemberAdvantageLevels ON dbo.UserMemberAdvantageLevels.MemberAdvantageLevelId = dbo.MemberAdvantageLevels.Id
WHERE
dbo.tbh_OrderStatuses.OrderStatusID = 4 AND
(dbo.tbh_Orders.AddedDate BETWEEN dateadd(year,-1,getdate()) AND GETDATE()) and IsCurrent = 1
GROUP BY
dbo.AZProfile.UserId,
dbo.AZProfile.UserName,
dbo.AzProfile.Email,
dbo.MemberAdvantageLevels.Name,
dbo.MemberAdvantageLevels.MinAmount,
dbo.MemberAdvantageLevels.MaxAmount,
dbo.UserMemberAdvantageLevels.LevelAchievmentDate,
dbo.UserMemberAdvantageLevels.LevelAchiementAmount,
dbo.UserMemberAdvantageLevels.IsCurrent,
dbo.MemberAdvantageLevels.Id
This hasn't been syntax checked or tested but should handle the inserts and updates you describe. The insert can be done as single statement using a derived/virtual table which contains the orders group by caluclation. Note that both the insert and update statement be done within the same transaction to ensure no two records for the same user can end up with IsCurrent = 1
INSERT UserMemberAdvantageLevels (UserId, MemberAdvantageLevelId, IsCurrent,
LevelAchiementAmount, LevelAchievmentDate)
SELECT t.UserId, mal.Id, 1, t.OrderTotals, GETDATE()
FROM
(SELECT ulp.UserId, SUM(ord.SubTotal) OrderTotals, COUNT(ulp.UserId) UserOrders
FROM UserLevelProfile ulp
INNER JOIN tbh_Orders ord ON (ord.CustomerId = ulp.UserId)
WHERE ord.StatusID = 4
AND ord.AddedDate BETWEEN DATEADD(year,-1,GETDATE()) AND GETDATE()
GROUP BY ulp.UserId) AS t
INNER JOIN MemberAdvantageLevels mal
ON (t.OrderTotals BETWEEN mal.MinAmount AND mal.MaxAmount)
-- Left join needed on next line in case user doesn't currently have a level
LEFT JOIN UserMemberAdvantageLevels umal ON (umal.UserId = t.UserId)
WHERE umal.MemberAdvantageLevelId IS NULL -- First time user has been awarded a level
OR (mal.Id <> umal.MemberAdvantageLevelId -- Level has changed
AND (t.OrderTotals > umal.LevelAchiementAmount -- Acheivement has increased (promotion)
OR t.UserOrders = 0)) -- No. of orders placed is zero (de-motion)
/* Reset IsCurrent flag where new record has been added */
UPDATE UserMemberAdvantageLevels
SET umal1.IsCurrent=0
FROM UserMemberAdvantageLevels umal1
INNER JOIN UserMemberAdvantageLevels umal2 On (umal2.UserId = umal1.UserId)
WHERE umal1.IsCurrent = 1
AND umal2.IsCurrent = 2
AND umal1.LevelAchievmentDate < umal2.LevelAchievmentDate)
One approach:
with cte as
(SELECT Sum(o.SubTotal) AS OrderTotals,
Count(p.UserId) AS UserOrders,
p.UserId,
p.UserName,
p.Email,
l.Name,
l.MinAmount,
l.MaxAmount,
ul.LevelAchievmentDate,
ul.LevelAchiementAmount,
ul.IsCurrent as IsCurrentLevel,
l.Id as MemberLevelId
FROM dbo.tbh_Orders o
INNER JOIN dbo.UserProfile p ON o.CustomerID = p.UserId
INNER JOIN dbo.UserMemberAdvantageLevels ul ON p.UserId = ul.UserId
INNER JOIN dbo.MemberAdvantageLevels l ON ul.MemberAdvantageLevelId = l.Id
WHERE o.StatusID = 4 AND
o.AddedDate BETWEEN dateadd(year,-1,getdate()) AND GETDATE() and
IsCurrent = 1
GROUP BY
p.UserId, p.UserName, p.Email, l.Name, l.MinAmount, l.MaxAmount,
ul.LevelAchievmentDate, ul.LevelAchiementAmount, ul.IsCurrent, l.Id)
select cte.*, ml.*
from cte
join #memLevels ml
on cte.OrderTotals >= ml.MinAmount and cte.OrderTotals <= ml.MaxAmount

How to check is a row value exists for each user in the database

I'm creating a database which tracks customer contact, the target contact date for initial contact is 90 working days from the first date that a custom calls us, I have created a function to handle this calculation.
I have a customer contact log table, which all contact is entered in to.
I have a mail script set up in mssql2005 which sends a list to a managers email box when either no contact has been made or the log was entered after the 90day period.
I'm struggling with the sql to determine if no contact exists or if it exist but is breached, please take a look at my script below :
I've attempted to make it as readable as possible.
DECLARE #tmp INT
SELECT m.id AS
[Case ID],
CONVERT(VARCHAR, userdbjhv25.dbo.Calcdate(oc.firstdate), 103) AS
[Target Contact Date]
FROM userdbjhv25.dbo.USER v,
userdbjhv25.dbo.customer o,
userdbjhv25.dbo.maincase m,
userdbjhv25.dbo.usercase vc,
userdbjhv25.dbo.customercase oc,
contactlist r
WHERE m.id = vc.caseid
AND v.userid = vc.userid
AND m.id = oc.caseid
AND o.customerid = oc.customerid
AND userdbjhv25.dbo.Calcdate(oc.firstdate) <= Getdate()
AND ( #tmp IS NOT NULL
AND NOT EXISTS (SELECT 1
FROM contactlist r1
WHERE r1.caseno = vc.usercase
AND r1.conlogtype = 'Initial Contact')
OR (( #tmp IN(SELECT 1
FROM contactlist r2,
usercase vc2,
USER v2,
customercase oc2,
maincase m2,
customer o2
WHERE m2.id = oc2.caseid
AND o2.customerid = oc2.customerid
AND r2.conlogtype = 'Initial Contact'
AND r2.caseno = vc.usercase
AND
userdbjhv25.dbo.Calcdate(oc2.firstdate) < r2.postdate
)
)) )
I think a left join is going to be your friend here. I'm not able to sufficiently visualize your schema, but the idea behind a left (or right join) is that data may not exist in one of the data sets. When that happens, a row full of nulls is returned. When it does match though, you get back the data that matched. So, some psedo-code:
select m.id AS [Case ID],
CONVERT(VARCHAR, userdbjhv25.dbo.Calcdate(oc.firstdate), 103) AS [Target Contact Date]
from userdbjhv25.dbo.customer o
left join userdbjhv25.dbo.customercase oc
on o.customerid = oc.customerid
where oc.firstdate is null or datediff(day, oc.firstdate, getdate()) > 90
Adapt this to your schema and you should be good to go.