SQL 2005 returning unique results with subquery - sql-server

I have a database Table a (EMAILS) where EmailID is the Primary Key
EmailID Email_To Email_From Email_Subject Email_Registered Email_Read
If a user creates an email it is registered in this table.
For example, the user "Dave" who has id 3 sends an email to "John" who has id 4
So this would give
EmailID Email_To Email_From Email_Subject Email_Registered Email_Read
10 4 3 TEST 2/23/2016 11:00 False
To return results I do this select (joining the user profile database)
SELECT PROFILE_1.SellerID, PROFILE_1.Seller_UserName, EMAILS.EmailID, EMAILS.Email_From, EMAILS.Email_To, EMAILS.Email_Subject,
EMAILS.Email_Registered, EMAILS.Email_Read,
(SELECT Seller_UserName AS Epr2
FROM PROFILE
WHERE (SellerID = EMAILS.Email_To)) AS Expr2
FROM PROFILE AS PROFILE_1 LEFT OUTER JOIN
EMAILS ON EMAILS.Email_From = PROFILE_1.SellerID
WHERE (EMAILS.Email_From IS NOT NULL) AND (PROFILE_1.Seller_UserName = 'Dave')
ORDER BY EMAILS.Email_Registered DESC
So John Replies to Dave's email and it goes into the EMAILS_THREAD table and is registered as
EmailThreadID EmailID Email_To Email_From Email_Registered Email_Read
1 10 3 4 2/23/2016 11:05 False
What I am trying to do is a select that
SELECTS from EMAILS where Email_From is from Dave and return in the results the top 1 result from EMAIL_THREADS that is sent to Dave (based on Email_Registered) with the same EmailID as the EMAILS.EmailID if there is a entry in EMAIL_THREADS.
So in other words return the result of the EMAIL table and latest corresponding result in the EMAIL_THREADS table if there is one.
I hope this makes sense.
I've tried a ton of combinations and I can't figure this out.
At first I thought it was a subquery or a join or a group by...but i can't seem to nail the select and how it is structured.
Looking for some help.
Here is my last attempt
SELECT PROFILE_1.SellerID, PROFILE_1.Seller_UserName, EMAILS.EmailID, EMAILS.Email_From, EMAILS.Email_To, EMAILS.Email_Subject,
EMAILS.Email_Registered, EMAILS.Email_Read,
(SELECT Seller_UserName AS Epr2
FROM PROFILE
WHERE (SellerID = EMAILS.Email_To)) AS Expr2
FROM PROFILE AS PROFILE_1 LEFT OUTER JOIN
EMAILS ON EMAILS.Email_From = PROFILE_1.SellerID CROSS JOIN
(SELECT TOP (1) EMAILS_THREAD.Email_From, EMAILS_THREAD.Email_To, EMAILS_THREAD.Email_Registered, EMAILS_THREAD.Email_Read
FROM EMAILS_THREAD LEFT OUTER JOIN
EMAILS AS EMAILS_1 ON EMAILS_THREAD.EmailID = EMAILS_1.EmailID) AS derivedtbl_1
WHERE (EMAILS.Email_From IS NOT NULL) AND (PROFILE_1.Seller_UserName = 'Dave')
ORDER BY EMAILS.Email_Registered DESC
But it's not returning anything from EMAILS_THREADS at all.

SELECTS from EMAILS where Email_From is from Dave and return in the results the top 1 result from EMAIL_THREADS that is sent to Dave (based on Email_Registered) with the same EmailID as the EMAILS.EmailID if there is a entry in EMAIL_THREADS.Hope this helps
with cte
as
(select
* from emails
where email_from=3
)
select * from cte mt --only for dave
outer apply
(
select top 1* from
emial_threads st where mt.mail_from=st.mail_to ---send to dave
and mt.emailid=st.emailid) b

Haven't been able to find a solution to this so I am paying a SQL professional to resolve this for me. Thanks for the input from Tab and The Gameiswar. Much appreciated.

Related

Select records when 2 column's data will match

I have two tables as shown below:
-----------------------
|EmpNo|Complaint |
-----------------------
|9091 |Change required|
|9092 |No change |
|9093 |Changes done |
-----------------------
Above table contains employee number and his complaints.
I have one another table which contains employee all kind of details as shown below.
-------------------------------
|EmpNo|EmailID |EmpBossNO|
-------------------------------
|9091 |abc#gmail.com|9092 |
|9092 |xyz#gmail.com|9093 |
|9093 |mno#gmail.com|9099 |
-------------------------------
Here, if Empno:9091 will raise any complain then a mail will send to his boss that the complain is raise by your employee and you have to accept it so I want to get EmailID of employee's boss and for that I want one SQL query. I tried the query shown here, but it doesn't work.
select EmpEmailID
from tblComplaint
inner join tblEmpMaster on tblEmpMaster.EmpNo = tblComplaint.EmpPSNo
where tblComplaint.EmpPSNo = tblEmpMaster.EmpBossNo
I want output like.. if complaint is raised by EmpNo:9091 then it will return EmailID of his boss which is xyz#gmail.com.
You are on the right track with a join between the tblComplaint and tblEmpMaster tables. But, you need an additional join to tblEmpMaster to bring in the boss' email for each employee complaint.
SELECT
c.EmpNo,
c.Complaint,
COALESCE(e2.EmailID, 'NA') AS boss_email
FROM tblComplaint c
INNER JOIN tblEmpMaster e1
ON c.EmpNo = e1.empNo
LEFT JOIN tblEmpMaster e2
ON e1.EmpBossNO = e2.EmpNo;
Demo
I used a left self join above, in case a given employee does not have a boss (e.g. for the highest ranking boss). In this case, I display NA for the boss email.
You should self join tblEmpMaster
select boss.EmpEmailID
from tblComplaint
inner join tblEmpMaster emp on emp.EmpNo = tblComplaint.EmpPSNo
inner join tblEmpMaster boss on boss.EmpNo = emp.EmpBossNO
where tblComplaint.EmpPSNo = 9091
DB Fiddle
you can even use sub queries to get the Email_Id of the boss as shown below
SELECT Email_Id
FROM EMP_Details
WHERE Emp_No IN (
SELECT Boss_Id
FROM Emp_Details) AND
Emp_No IN (
SELECT Emp_No
FROM Emp_Complaints)

Running 3-Tier T-SQL Query for Report

First question here so please excuse any mistakes...
I am trying to write a SQL Query for an SSRS report and I am totally confused when it comes to my joins.
Background: I have 3 tables that are relevant
Publishers - This is essentially a list of people
Publisher Reports - This is a list of records (related to the Publisher table) that details the work they have completed in a month period.
Report Months - This is a list of records (related to the Publisher Reports table) that relates to a specific month and year. On these records they have an indicator to show whether they relate to the previous six month period.
What i am trying to do is get a list of Publishers who have not submitted a publisher report that is related to a Report Month record within the last 6 months. My desired output is a list of Publishers in on column with the Report Month(s) that they are missing in the next column.
I am really struggling how to do it... I had thought of it as a three step process...
--STEP 1 - Get list of report months that are included in the last 6 months
WITH ACTIVE6MREPM AS
(
SELECT r.jajw_name,
r.jajw_CalendarDate
FROM jajw_reportmonthBase r
WHERE r.jajw_IncludedIn6MonthReport = '1'
),
--STEP 2 - Get list of all publishers
ACTIVEPUBS AS
(
SELECT c.FullName,
c.ContactId
FROM ContactBase c
WHERE c.statecode = '0'
AND c.jajw_CongregationAssignment != 640840001
AND c.jajw_CongregationAssignment != 640840006
AND c.jajw_CongregationAssignment != 640840005
--AND q.jajw_FieldServiceGroups = (#Field_Service_Group)
),
--STEP 3 - Get List of Publisher Reports for the selected Report Months
RELEVANTREPORTS AS
(
SELECT r.jajw_reportId AS Publisher_Report_GUID,
r.jajw_PublisherId AS Publisher_GUID,
r.jajw_ReportMonthId AS ReportMonth_GUID,
m.jajw_name AS ReportMonth_Name
FROM jajw_reportBase r
INNER JOIN jajw_reportmonthBase m ON r.jajw_ReportMonthId = m.jajw_reportmonthId
WHERE r.jajw_ReportPeriod6Month = '1'
ORDER BY m.jajw_CalendarDate
After these three, I want to create my list as described above and this is the bit that has me stumped! Any help would be greatly appreciated!
Thanks!
I think you can shorten your code a lot... here's a shot at it without having test data... be sure to read the comments and add in the join condition and check the where clause.
with cte as(
SELECT r.jajw_reportId AS Publisher_Report_GUID,
r.jajw_PublisherId AS Publisher_GUID,
r.jajw_ReportMonthId AS ReportMonth_GUID,
m.jajw_name AS ReportMonth_Name,
c.FullName,
c.ContactId
FROM jajw_reportBase r
INNER JOIN jajw_reportmonthBase m ON
r.jajw_ReportMonthId = m.jajw_reportmonthId
INNER JOIN ContactBase c on --what ever condition is appropiate
WHERE r.jajw_ReportPeriod6Month = '1'
and m.jajw_IncludedIn6MonthReport = '1' --maybe put this here, or does the above do the same thing?
ORDER BY m.jajw_CalendarDate)
select
p2.FullName,
p2.ReportMonth_Name
from cte p
right join(select distinct
ReportMonth_Name, FullName
from ContactBase
left join jajw_reportmonthBase on 1=1) p2 on p2.FullName = p.FullName and p2.ReportMonth_Name = p.ReportMonth_Name
where
ContactId in (select ContactId from cte group by ContactId having count(distinct ReportMonth_GUID) < 6)
and p.FullName is null
Here is an example using test data.
declare #pub table (pubname varchar(56), ReportMonthName varchar(16))
insert into #pub (pubname,ReportMonthName) values
('a','Jan'),
('a','Feb'),
('a','Mar'),
('a','Apr'),
--publisher a is missing May and Jun
('b','Jan'),
('b','Feb'),
('b','Mar'),
('b','Jun')
--publisher b is missing Apr and May
declare #dt table (ReportMonthName varchar(16))
insert into #dt (ReportMonthName) values
('Jan'),
('Feb'),
('Mar'),
('Apr'),
('May'),
('Jun')
select
p2.pubname
,p2.ReportMonthName
from #pub p
right join(
select distinct
p.pubname
,d.ReportMonthName
from #pub p
left join #dt d on 1=1)p2 on p2.pubname = p.pubname and p2.ReportMonthName = p.ReportMonthName where p.pubname is null

SQL Server Simple Query

I have this tables on my database
Users,Courses,Semesters,SelectedCourses
Users : ID,Username,Password,EnterYear
Courses : ID,Name
Semesters : ID,Code
SelectedCourses : ID,SemesterID(FK to Semesters.ID),UserID(FK to Users.ID),CourseID(FK to Courses.ID)
Now, I have 2 or n CourseID and I want to get Users that selected this Courses together.
for example :
This is my SelectedCourses table :
Result must be :
I want to find Users that have CourseID(1) and CourseID(2) on their SelectedCourses list.
Only UserID = 1 have this two courses!
SELECT U.UserID
FROM Users U
WHERE NOT EXISTS ( SELECT C.CID
FROM Course C
WHERE C.CId in (1,2) AND
NOT EXISTS
(SELECT S.CID
FROM SelectedCourses S
WHERE S.CID = C.CID AND
S. UserID = U.UserID)
);
For each user we check that there is no course that is not taken by this user.
This works as long as the number of course is within the range of data type.
select
userId,count(distinct courseId)
from
selectedCourses
where
courseId in (1,2)
group by userId
having count(distinct courseId) > 1

When a SQL Server query returns no rows(NOT null rows) how do you include that in an aggregate function?

I'm writing a query to look for courses that do not have any of its gradable items graded.
In Blackboard when a user doesn't have a grade at all(e.g. no attempt was ever made) there simply isn't a row in the table gradebook_grade
So if a course doesn't have any grades at all the gradebook_grade table does not have any rows referencing the primary key of the Blackboard course_id
This is what I've used so far:
use bblearn
select cm.course_id
from course_main cm
join gradebook_main gbm on cm.pk1 = gbm.crsmain_pk1
join gradebook_grade gbg on gbm.pk1 = gbg.gradebook_main_pk1
where cm.pk1 = 3947
group by cm.course_id
having count(gbg.pk1) <= 0
The course in question(pk1 3947) is confirmed to not have any grades. So SQL Server says 0 rows affected, naturally.
The thing is, it doesn't select the course_id. I'm guessing having doesn't account for blank/non-existent rows. Is there a way to structure the query to get the course ID when there isn't anything returned? Am I joining on the wrong columns or using where on the wrong column? Any help is appreciated.
Use a left join
select cm.course_id
from course_main cm
left join gradebook_main gbm on cm.pk1 = gbm.crsmain_pk1
left join gradebook_grade gbg on gbm.pk1 = gbg.gradebook_main_pk1
where cm.pk1 = 3947
group by cm.course_id

SQL Server : join only one table

Let's say that I have those four tables.
PEOPOLE
ID NAME SURNAME COMPANY UNIT GROUPS
--------------------------------------------
1 Michael Backer 1 1 1
2 Travis Morgan 2 2 2
3 George Marshall 3 3 3
COMPANY
ID NAME
------------
1 Coca Cola
2 Pepsi
3 Sprite
WORKUNIT
ID NAME
-------------
1 Finances
2 Marketing
3 Sales
GROUPS (both values can be null)
ID NAME FLOOR
-------------------------
1 Risks 5
2 NULL NULL
3 Secretariat NULL
Expected results
NAME SURNAME COMPANYNAME WORKUNIT GROUPS FLOOR
-----------------------------------------------
Michael Backer Coca Cola Finances Risks 5
Travis Morgan Pepsi Marketing NULL NULL
George Marshall Sprite Sales Secretariat NULL
So far I write this query with no success:
SELECT
people.NAME, people.SURNAME, company.NAME,
workunit.NAME, groups.NAME, groups.FLOOR
FROM
company, workunit, groups, people
LEFT JOIN
groups on people.GROUP = GROUPS.id
WHERE
company.id = people.company AND
workunit.id = people.unit AND
groups.id = people.group AND
groups.floor = 'something from textbox';
I am not familiar with combining join statements in more than one table, so please help me out because I'm stuck.
Just write like this:
SELECT
people.NAME,
people.SURNAME,
company.NAME,
workunit.NAME,
groups.NAME,
groups.FLOOR
FROM
people
INNER JOIN GROUP
ON people.GROUP=GROUPS.id
INNER JOIN company
ON people.company=company.id
INNER JOIN UNIT
ON people.UNIT =UNIT.id
WHERE
GROUPS.floor='something from textbox';
I verified your query in SQL Server. You need to modify it a little bit, at least, to see it executing, in this way:
SELECT
people.NAME, people.SURNAME, company.NAME,
workunit.NAME, groups.NAME, groups.FLOOR
FROM
company, workunit, people
LEFT JOIN
groups on people.GROUP = GROUPS.id
WHERE
company.id = people.company AND
workunit.id = people.unit AND
groups.id = people.group AND
groups.floor = 'something from textbox';
Anyway, your query doesn't work because, even if you want the results in the way you described using a LEFT JOIN, you are setting the condition:
AND groups.floor = 'something from textbox';
In this way, you won't be able to see the records where there isn't a match with the GROUPS table, because you're saying explicitly that you want the records where the value of the column floor must be equal to 'something from textbox'.
If you want also the non-matches you can replace the condition with:
OR groups.floor = 'something from textbox';
but you will have some duplicates and a group by statement won't work anyway.
Then, you have to check if you really want those expected results.
I didn't understand why you want also the non-matches, even if you are looking for the precise result, using groups.floor = 'something from textbox'. If you want to display the results in a GUI, the non-matches would be useless information for a user, in my opinion.
SELECT people.NAME, people.SURNAME, company.NAME, workunit.NAME, groups.NAME, groups.FLOOR
FROM company, workunit, groups LEFT JOIN people on people.GROUP=GROUPS.id
WHERE
company.id=people.company AND
workunit.id=people.unit AND
groups.id=people.group AND
groups.floor='something from textbox';

Resources