Iteration between 2 tables SQL Query - sql

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

Related

I'm getting 0, however, I know that there are some new customers

Please help me - I'm trying to get only new customers of each month.
Here's my logic: emails of this month with a where not exists in all records before the month.
SELECT COUNT(email)
FROM `bc_order_billing_addresses`
WHERE NOT EXISTS (SELECT email
FROM `bc_order_billing_addresses`
LEFT JOIN `bc_order` ON `.bc_order`.order_id = `bc_order_billing_addresses`.order_id
WHERE order_created_date_time < '2022-10-01T00:00:00');
I'm getting 0, however, I know that there are some new customers. (edited)
I tried HoneyBadger's suggestion in the comments. It works!
SELECT DISTINCT count(email)
FROM `my-project-24hr-339515.data_24hr.bc_order_billing_addresses`
WHERE email NOT IN (
SELECT email
FROM `my-project-24hr-339515.data_24hr.bc_order_billing_addresses`
left join `my-project-24hr-339515.data_24hr.bc_order`
On `my-project-24hr-339515.data_24hr.bc_order`.order_id = `my-project-24hr-339515.data_24hr.bc_order_billing_addresses`.order_id
where order_created_date_time < '2022-10-01T00:00:00'
);

MS SQL count values for per row for per id

I'm trying to count incident types per depot. My current query returns the following result set:
I then apply a count query on this set which looks like this:
select middleList.DepotName as depot,
count(middleList.NearMiss) as NearMiss,
count(middleList.Theft) as Theft,
count(middleList.Security) as Security,
count(middleList.LostTimeDisablingInjury) as LostTimeDisablingInjury,
count(middleList.Fire) as Fire,
count(middleList.OccupationalIllness) as OccupationalIllness,
count(middleList.VehicleAccident) as LostTimeDisablingInjury,
count(middleList.Spliiage) as Fire,
count(middleList.PropertyDamage) as OccupationalIllness,
count(middleList.NonConformance) as NonConformance,
count(middleList.Other) as Other
from
(SELECT dbo.IncidentTypes.NearMiss, dbo.IncidentTypes.Theft,
dbo.IncidentTypes.Security, dbo.IncidentTypes.LostTimeDisablingInjury,
dbo.IncidentTypes.Fire, dbo.IncidentTypes.OccupationalIllness,
dbo.IncidentTypes.VehicleAccident, dbo.IncidentTypes.Spliiage,
dbo.IncidentTypes.PropertyDamage, dbo.IncidentTypes.NonConformance,
dbo.IncidentTypes.Other, dbo.Incidents.IncidentTitle, dbo.Depots.DepotName,
dbo.Incidents.IncidentNumber
FROM dbo.Departments INNER JOIN
dbo.Depots ON dbo.Departments.DepotId = dbo.Depots.DepotId
INNER JOIN
dbo.Employees ON dbo.Departments.DepartmentId =
dbo.Employees.DepartmentId INNER JOIN
dbo.IncidentTypes INNER JOIN
dbo.Incidents ON dbo.IncidentTypes.IncidentTypeId =
dbo.Incidents.IncidentTypeId ON dbo.Employees.EmployeeId =
dbo.Incidents.EmployeeId_EmployeeInvolv
Where Incidents.DateCreated = (SELECT MAX (i2.DateCreated) FROM
Incidents as i2 WHERE Incidents.IncidentNumber = i2.IncidentNumber)) as
middleList
group by middleList.DepotName
Which return the following incorrect results:
Please help.
Okay so I found the problem.
It seems like the rows are being counted and not the actual values, thus adding this to the count insured that they were being counted properly:
count(case when middleList.NearMiss <> '0' then 0 end ) as NearMiss
End result being:

How to combine two different SQL queries in one SQL statement?

I have two tables which are:
Members
Member_id | Member_user_name | Member_account_id
and
Members_transaction
Member_id (sender) | Member_transaction_id | Member_account_id (recipient) | Amount | from_to
All columns have data but from_to is a new column added. I would like to add the username of sender or recipient into the column from_to.
I had use below SQL query to find out the sender's or recipient's username:
select member_user_name member_involved
from Members_transaction
left
join members
on members_transaction.member_account_id = members.member_account_id
I want to add the SQL query in this SQL query:
SELECT member_transaction_id
, mp.member_account_id
, m.member_user_name
, amount
, CASE
-- when the amount starts with "-" such as "-100" it means paid to recipient
WHEN amount LIKE '-%' THEN 'Paid to' + member_involved
-- else it is received from the sender
ELSE ' Received from '+ member_involved
END AS from_to
FROM members_transaction MP (nolock)
LEFT
JOIN members M (NOLOCK)
ON M.MEMBER_ID = MP.MEMBER_ID
AND M.IS_USE = 1
WHERE MP.IS_USE = 1
Since the condition is different (the ON), how can i combine the SQL query of finding sender or recipient into the below SQL query?
You can join twice with members, once for the sender name, once for the receiver name:
SELECT member_transaction_id
, mp.member_account_id
, m.member_user_name
, amount
, CASE
-- when the amount starts with "-" such as "-100" it means paid to recipient
WHEN amount LIKE '-%' THEN 'Paid to' + M2.member_user_name
-- else it is received from the sender
ELSE ' Received from '+ M.member_user_name
END AS from_to
FROM members_transaction MP (nolock)
LEFT JOIN members M (NOLOCK) ON M.MEMBER_ID = MP.MEMBER_ID AND M.IS_USE = 1
LEFT JOIN members M2 (NOLOCK) ON M2.member_account_id = MP.member_account_id AND M2.IS_USE = 1
WHERE MP.IS_USE = 1

Create Stored procedure for setting reminder for document created

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

Joining a derived table postgres

I have 4 tables:
Competencies: a list of obviously competencies, static and a library
Competency Levels: refers to an associated group of competencies and has a number of competencies I am testing for
call_competency: a list of all 'calls' that have recorded the specified competency
competency_review_status: proving whether each call_competency was reviewed
Now I am trying to write this query to count a total and spit out the competency, id and whether a user has reached the limit. Everything works except for when I add the user. I am not sure what I am doing wrong, once I limit call competency by user in the where clause, I get a small subset that ONLY exists in call_competency returned when I want the entire list of competencies.
The competencies not reached should be false, ones recorded appropriate number true. A FULL list from the competency table.
I added the derived table, not sure if this is right, obviously it doesn't run properly, not sure what I'm doing wrong and I'm wasting time. Any help much appreciated.
SELECT comp.id, comp.shortname, comp.description,
CASE WHEN sum(CASE WHEN crs.grade = 'Pass' THEN 1 ELSE CASE WHEN crs.grade = 'Fail' THEN -1 ELSE 0 END END) >= comp_l.competency_break_level
THEN TRUE ELSE FALSE END
FROM competencies comp
INNER JOIN competency_levels comp_l ON comp_l.competency_group = comp.competency_group
LEFT OUTER JOIN (
SELECT competency_id
FROM call_competency
WHERE call_competency.user_id IN (
SELECT users.id FROM users WHERE email= _studentemail
)
) call_c ON call_c.competency_id = comp.id
LEFT OUTER JOIN competency_review_status crs ON crs.id = call_competency.review_status_id
GROUP BY comp.id, comp.shortname, comp.description, comp_l.competency_break_level
ORDER BY comp.id;
(Shooting from the hip, no installation to test)
It looks like the below should do the trick. You apparently had some of the joins mixed up, with a column from a relation that was not referenced. Also, the CASE statement in the main query could be much cleaner.
SELECT comp.id, comp.shortname, comp.description,
(sum(CASE WHEN crs.grade = 'Pass' THEN 1 WHEN crs.grade = 'Fail' THEN -1 ELSE 0 END) >= comp_l.competency_break_level) AS reached_limit
FROM competencies comp
JOIN competency_levels comp_l USING (competency_group)
LEFT JOIN (
SELECT competency_id, review_status_id
FROM call_competency
JOIN users ON id = user_id
WHERE email = _studentemail
) call_c ON call_c.competency_id = comp.id
LEFT JOIN competency_review_status crs ON crs.id = call_c.review_status_id
GROUP BY comp.id, comp.shortname, comp.description
ORDER BY comp.id;