SQL 101 - Counts By Location and Grade

Goog Feed, General, SQL    Comments (0)



The Desired Result

The other day at work there was a need for a report that our reporting system was having trouble putting out. So the fix was to write it ourselves. It's not too complex and for some it may be quite elementary, but here it is none-the-less.

Being that I work for a school district there was a need for a report by campus and grade level of the number of students that fell into a certain category. So for the sake of this report we want a count of all active students based on their campus and their grade level.

Below is the stripped down version of how this was accomplished.

SELECT Campus, Grade, COUNT(studentID) AS StudentCount
FROM ourStudentTable
WHERE studentStatus = 'A'
GROUP BY Campus, Grade
ORDER BY Campus

Hopefully this helps!

SQL - Using Sub Queries As Joining Tables

Goog Feed, General, SQL    Comments (2)


Today at work I faced a dilemma. I was tasked with developing a function in which a parent could be notified when their child has an absence or a tardy in one of their classes (I work for a school district). It involved touching 3 different tables including one twice. The three types of tables are as follows, an attendance details table which we'll call AttendanceDetail, a parent/student table which ties parents with students which we'll call ParentStudent, and finally a notify parent when an absence occurs table which we'll call AttendanceNotification.

So here is the short of how the process works. Daily a routine will run checking to see if a student whose parent requested a notification upon an attendance event had missed a class and/or was tardy to class. Sounds simple enough huh? Well it wasn't as easy as first thought.

My first query was as follows...

SELECT an.studentID, ps.studentFirstName, ps.studentLastName, ad.absence_date
FROM AttendanceNotification an
INNER JOIN ParentStudent ps ON ps.studentID = an.studentID
INNER JOIN AttendanceDetail ad ON ad.studentID = an.studentID
WHERE an.notify = 1 AND ps.status = 'A'

Basically this query grabs all prior absence events for a student where they are active and the parent needs to be notified of the last absence event. So we have a bunch of unwanted events here, we just need the most recent event.

Simple enough we'll just add a couple things to our query and we'll be good to go right? Not so fast. So I added a MAX() function to the absence date which would give me the most recent absence and I grouped by the studentID which would only give me one record back per student and I ended up with the following.

SELECT an.studentID, ps.studentFirstName, ps.studentLastName, MAX(ad.absence_date) AS absenceDate
FROM AttendanceNotification an
INNER JOIN ParentStudent ps ON ps.studentID = an.studentID
INNER JOIN AttendanceDetail ad ON ad.studentID = an.studentID
WHERE an.notify = 1 AND ps.status = 'A'
GROUP BY an.studentID, ps.studentFirstname, ps.studentLastname

Well, the problems began to start, I needed to be able to show the parent what the absence event detail was. Did their student have a tardy? An unexcused absence? A doctors appointment? You get the point. My first thought was to just add it into the SELECT statement for the above query, but then I had to include them in my GROUP BY clause which caused more than one record per student to be returned. I then thought about trying to wrap them in a MAX function, that didn't work, they needed an aggregate function to be included in my SELECT criteria and not in my GROUP BY, I was at a loss.

Then I got an idea, I wondered if I could JOIN on a sub query. I had never tried it before, but it worked perfectly! I thought I'd share it with you just in case you ever ran across a similar problem.

The final query does an INNER JOIN from the AttemdanceDetail table to the previous result set or sub query. Now we're able to get detailed absence info yet only the most recent record. Here is the final query.

SELECT
   a.studentID,
   a.studentFirstName,
   a.studentLastName,
   a.absenceDate,
   CASE WHEN ltrim(rtrim(adII.am_office_abs)) IS NULL THEN ltrim(rtrim(adII.am_teacher_abs)) ELSE ltrim(rtrim(adII.am_office_abs)) END AS am,
   CASE WHEN ltrim(rtrim(adII.pm_office_abs)) IS NULL THEN ltrim(rtrim(adII.pm_teacher_abs)) ELSE ltrim(rtrim(adII.pm_office_abs)) END AS pm
FROM AttendanceDetail adII
INNER JOIN
(SELECT an.studentID, ps.studentFirstName, ps.studentLastName, MAX(ad.absence_date) AS absenceDate
FROM AttendanceNotification an
INNER JOIN ParentStudent ps ON ps.studentID = an.studentID
INNER JOIN AttendanceDetail ad ON ad.studentID = an.studentID
WHERE an.notify = 1 AND ps.status = 'A'
GROUP BY an.studentID, ps.studentFirstname, ps.studentLastname) a
ON a.studentID = adII.studentID AND a.absenceDate = adII.absence_date

Perhaps there is a better way to do this, I just don't know how, but this worked so I ran with it.

CFUnited: My Recap

Goog Feed, General, ColdFusion, CFUnited 2008, SQL    Comments (0)


CFUnited 2008 was a great experience for me personally, I presented as a speaker for the first time which was a great experience and challenge, as well as learned a great deal of things that I would like to put into practice in my own development environment.

I wanted to put a quick post out there to go over some of the highlights that I was able to take away learning wise for others to see as well as a constant reminder to myself. So, what did I personally learn?

  • In his own words, Ray Camden will be using tables for layout until someone stops him... Should've come to my session Ray!
  • I want to start using CFToolTip more for my end-users benefit.
  • There is a cool Event Validator at RiaForge that Mark Drew referenced, I would like to check into that when I get the time.
  • From Hal Helms session, leave functions open for extention, closed for changes. Keeping things simple
  • Just because MVC is used, doesn't mean I'm doing OO. I can still be doing procedural code in an MVC format.
  • Get book called Design Patterns by Gang of Four
  • Find the things that are constantly changing in my applications and encapsulate them.
  • Good OO is all about abstraction.
  • Pass objects to be persisted.
  • From Chris Scott's session, keep ColdSpring simple - getBeans/setBeans
  • Increase the JVM default on the CF Server.
  • Increase the minimum memory on the CF Server.
  • Turn on trusted cache in production.
  • Cache queries used often in applications.
  • Read the CF8 performance brief.
  • Use SQL Server performance monitoring tools to profile, trace, look at execution plans and their costs, run database reports to see which queries are putting loads on the server.
  • If session is not available, reject the form submission, because it means they didn't come from your form.
  • From Joe's advanced Model-Glue session... you can use the include tags to include entire applications into your Model-Glue app.
  • Prefix event handlers.
  • Controllers should be as thin as possible.
  • Use views for common joins, filtering, etc... when dealing with larger queries.
  • Index all fields searched on in my SQL tables for fast searching and less load on the database. A good example of this is looking for pizza in the phone book, but searching every page of the book from A-Z. With indexing you don't need to search from A-Z simply jump to 'Pizza'.
  • SQL views can be about 75% faster than CF for complex queries.
  • Stored procedures can be about 90% faster than CF.
  • Use cfQueryParams for security as well as not making the SQL Server re-write execution plans everytime a query is run.
  • Be careful about how you index your tables, you could do more damage than good if it's not done right.

That was my quick recap of what I learned. Overall the venue was great, I loved the fact that the conference was in downtown DC instead of Bethesda, the hotel was awesome and close to the conference. Another great job by the CFUnited team. I hope to return in 2009.

SQL Dynamic Date Range

Goog Feed, General, ColdFusion, SQL    Comments (0)


I work for a school district here in Texas and today an issue arose. We needed to run a nightly SQL job which pulls students from our Student Information System and dumps them into some tables we use for a local application. Problem is while we have about 22,000 active students our total student table has over 55,000 records in it, some from prior years.

The initial reaction was to hard-code the school year start and end dates into the system, but then if our DBA leaves, or we forget what kind of lame hack we put in place we have problems next school year.

I had done this previously in ColdFusion, but today I decided to do a SQL version of it. It will take the current day and decides what the current school year start and end dates are based on the current day, so we're always pulling current data only no matter what year it may be.

DECLARE @startDate datetime
DECLARE @endDate datetime

SET @startDate = cast('7/1/' + cast(datePart("yyyy",getDate()) AS varchar) AS datetime)
SET @endDate = cast('6/30/' + cast(datePart("yyyy",getDate()) AS varchar) AS datetime)

SET @startDate = CASE WHEN cast(@startDate AS datetime) > getDate() THEN cast(dateAdd("yyyy",-1,@startDate) AS datetime) ELSE cast(@startDate AS datetime) END
SET @endDate = CASE WHEN cast(@endDate AS datetime) < getDate() THEN cast(dateAdd("yyyy",1,@endDate) AS datetime) ELSE cast(@endDate AS datetime) END

SELECT @startDate AS startDate, @endDate AS endDate

The end result is 7/1/2007 as the startDate and 6/30/2008 for the endDate. It works perfect for us, and I hope it works for you.

Web Development - How do you approach it?

Goog Feed, General, ColdFusion, SQL    Comments (4)


I work for a school district, and I am the first developer they have every had. So I've been developing web apps for them for about six months now using ColdFusion with Model-Glue and SQL, all authentication is done through Active Directory.

Lately I started thinking about the future and how to best do development. When I was hired they had a list of projects they needed done, and they needed to be done yesterday. So I began coding, coding, coding. No design docs, not project scope docs, no database diagrams, nothing of the sort.

My first thought was to slow down and start a process for each project thrown my way. It may be more tedious, time-consuming and boring, but I really think long-term, a well laid out play with an approval process up front lends itself to successful projects.

I am a big fan of the Interface-Driven approach to web development, but I wanted to get some feedback from the community...

What methods/steps do you employ when taking on a project?
Do you build out pieces and release them or wait till the project is complete?
What type of documentation is used and why?
What have you found most beneficial to you in your experience with this?

Thanks in advance for your input!

More Entries