Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 145
  • Last Modified:

Query multiple tables (joins) for entries, but detecting missing entries

I have a reporting system which our students are required to utilize.  I need to run a report off the database (which I developed) that links to an external database (our Student Information System).

My database doesn't use names, just student IDs.  I need to query the SIS for the student's first and last name.  Below is the query I am using -- which is working to give me all of the report entries and whether or not they were on-time or late.  What I am not getting are the missing entries.  We need to no if a student did not report at all for that week.  I feel like I'm close, but I'm not sure what I'm doing wrong.  I will include some sample data and the SQL query.

Query
WITH students (StudentID) AS
(
	SELECT n.soc_sec AS [StudentID]
	FROM [LINKEDSERVER].[SIS].[dbo].[name] n INNER JOIN [LINKEDSERVER].[SIS].[dbo].[nmcrs] c
		ON n.soc_sec = c.soc_sec
	WHERE c.course='REQU0007' AND c.enrollcode='EN' AND c.sch_yr='201415' AND c.semester='1'
),

reportstd (Report, ReportPeriod, LateOn) AS
(
	SELECT CONVERT(varchar(10),s.reportOpen,102) AS [Report],
		   CONVERT(varchar(10),s.reportBegin,102) + ' - ' + 
	       CONVERT(varchar(10),s.reportEnd,102) AS [ReportPeriod],
		   s.lateOn AS [LateOn]
	FROM reports s
	WHERE s.reportOpen BETWEEN '08/01/2014' AND GETDATE()
)

SELECT nm.soc_sec AS [StudentID],
	   nm.last_name AS [LastName],
	   nm.first_name AS [FirstName],
	   s.ReportPeriod,
	   s.Report,
	   [Status] = CASE
			WHEN r.submitted > s.LateOn THEN 'LATE'
			WHEN r.submitted < s.LateOn THEN 'ON TIME'
			WHEN r.submitted IS NULL THEN 'NO REPORT'
			END
FROM [LINKEDSERVER].[SIS].[dbo].[name] nm LEFT JOIN Reported r
	ON nm.soc_sec = r.student LEFT JOIN reportstd s
	ON r.csgTerm = s.Report
WHERE (r.student IN (SELECT StudentID FROM students) OR
	  r.student NOT IN (SELECT StudentID FROM students)) AND
	  ReportPeriod IS NOT NULL AND
	  Report IS NOT NULL
ORDER BY LastName, FirstName, s.Report

Open in new window


Sample Data
name.txt
reports.txt
reportstd.txt
students.txt
reported.txt
0
Shane Kahkola
Asked:
Shane Kahkola
  • 4
  • 3
1 Solution
 
RayData AnalystCommented:
Your Inner Join in the 'with' section is eliminating those students who did not report at all.  Change it to a left join to get all student records.

This section MAY also be eliminating non reporters.
ReportPeriod IS NOT NULL AND
        Report IS NOT NULL


Indispensable tool for understanding joins . . .
http://www.codeproject.com/KB/database/Visual_SQL_Joins/Visual_SQL_JOINS_orig.jpg
0
 
RayData AnalystCommented:
This might be a silly question, but why are you doing this part (pasted below)?  It is effectively a non condition since it allows for all r.students whether they have a student ID or not.  If you are building this in some other application and need a 'placeholder' where you may or may not add 'and's, might I suggest replacing that piece with "Where 1=1"


WHERE (r.student IN (SELECT StudentID FROM students) OR
        r.student NOT IN (SELECT StudentID FROM students))
0
 
Shane KahkolaDirector of I.T.Author Commented:
Thank you, Ray, I will try your suggestions, and read the chart you posted.

The reason I did that last part was a desperation attempt to get all the records.  I really could not reiterate to you why I did it -- mainly because it doesn't make sense to me any more.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Shane KahkolaDirector of I.T.Author Commented:
I've requested that this question be closed as follows:

Accepted answer: 0 points for ccbbc_cs's comment #a40306314

for the following reason:

Ray, you were a God-send.

The chart and the questions led me in the right direction.  I finally did this, and got what I was looking for:

WITH students (StudentID,LastName,FirstName) AS
(
	SELECT n.soc_sec AS [StudentID],n.last_name AS [LastName],n.first_name AS [FirstName]
	FROM [LINKEDSERVER].[SIS].[dbo].[name] n INNER JOIN [LINKEDSERVER].[SIS].[dbo].[nmcrs] c
		ON n.soc_sec = c.soc_sec
	WHERE c.course='REQU0007' AND c.enrollcode='EN' AND c.sch_yr='201415' AND c.semester='1'
),

reportstd (Report, ReportPeriod, LateOn,ID) AS
(
	SELECT CONVERT(varchar(10),s.reportOpen,102) AS [Report],
		   CONVERT(varchar(10),s.reportBegin,102) + ' - ' + 
	       CONVERT(varchar(10),s.reportEnd,102) AS [ReportPeriod],
		   s.lateOn AS [LateOn],s.ID
	FROM reports s
	WHERE s.reportOpen BETWEEN '08/01/2014' AND GETDATE()
)

SELECT DISTINCT s.StudentID,
	   s.LastName,
	   s.FirstName,
	   [ReportPeriod] = CASE
				WHEN rs.ReportPeriod IS NULL THEN 'NEVER REPORTED'
				WHEN rs.ReportPeriod IS NOT NULL THEN rs.ReportPeriod
			     END,
	   [Report] = CASE
			WHEN rs.Report IS NULL THEN 'NEVER REPORTED'
			WHEN rs.Report IS NOT NULL THEN rs.Report
		       END,
	   rs.ID,
	   [Status] = CASE
			WHEN r.submitted > rs.LateOn THEN 'LATE'
			WHEN r.submitted < rs.LateOn THEN 'ON TIME'
			ELSE 'NO REPORT'
		      END
FROM reportstd rs LEFT JOIN Reported r
	ON rs.Report = r.csgTerm RIGHT JOIN students s 
	ON r.student = s.StudentID
ORDER BY LastName, FirstName, Report

Open in new window


This gave me the results I was looking to see.  Thanks again.
0
 
Shane KahkolaDirector of I.T.Author Commented:
Ray, you were a God-send.

The chart and the questions led me in the right direction.  I finally did this, and got what I was looking for:

WITH students (StudentID,LastName,FirstName) AS
(
	SELECT n.soc_sec AS [StudentID],n.last_name AS [LastName],n.first_name AS [FirstName]
	FROM [LINKEDSERVER].[SIS].[dbo].[name] n INNER JOIN [LINKEDSERVER].[SIS].[dbo].[nmcrs] c
		ON n.soc_sec = c.soc_sec
	WHERE c.course='REQU0007' AND c.enrollcode='EN' AND c.sch_yr='201415' AND c.semester='1'
),

reportstd (Report, ReportPeriod, LateOn,ID) AS
(
	SELECT CONVERT(varchar(10),s.reportOpen,102) AS [Report],
		   CONVERT(varchar(10),s.reportBegin,102) + ' - ' + 
	       CONVERT(varchar(10),s.reportEnd,102) AS [ReportPeriod],
		   s.lateOn AS [LateOn],s.ID
	FROM reports s
	WHERE s.reportOpen BETWEEN '08/01/2014' AND GETDATE()
)

SELECT DISTINCT s.StudentID,
	   s.LastName,
	   s.FirstName,
	   [ReportPeriod] = CASE
				WHEN rs.ReportPeriod IS NULL THEN 'NEVER REPORTED'
				WHEN rs.ReportPeriod IS NOT NULL THEN rs.ReportPeriod
			     END,
	   [Report] = CASE
			WHEN rs.Report IS NULL THEN 'NEVER REPORTED'
			WHEN rs.Report IS NOT NULL THEN rs.Report
		       END,
	   rs.ID,
	   [Status] = CASE
			WHEN r.submitted > rs.LateOn THEN 'LATE'
			WHEN r.submitted < rs.LateOn THEN 'ON TIME'
			ELSE 'NO REPORT'
		      END
FROM reportstd rs LEFT JOIN Reported r
	ON rs.Report = r.csgTerm RIGHT JOIN students s 
	ON r.student = s.StudentID
ORDER BY LastName, FirstName, Report

Open in new window


This gave me the results I was looking to see.  Thanks again.
0
 
Shane KahkolaDirector of I.T.Author Commented:
I did something dumb here, but I don't know how to fix it.  I wanted to award you the points and I must have clicked on something wrong.
0
 
RayData AnalystCommented:
Glad I could help in some way.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now