Using MAX() in a SQL Subquery

database diagram showing table relationships

One pro bono project I’m working on is improving a school website where parents can sign up for classes, view students’ grades, etc. One of the problems with the website was that the list of user accounts, which includes all parents and teachers, includes parents from previous years who no longer have students there.

The query for pulling this information was very simple:

SELECT * FROM UserAccounts ORDER BY lastName ASC

This query pulled all users and ordered them only by last name. The data was being dumped into an ASP.NET GridView with column sorting, and there were only a couple hundred people there, so it wasn’t completely unmanageable. However, dealing with all the parents who no longer have kids there did make visual searches more difficult. The request was to bring all current parents to the top of the list so that other admins don’t have to search through pages of people who no longer attend.

A quick fix for this would be to sort the list based on last academic year attended. We’ll do this by employing the MAX() function.

In addition to the UserAccounts table, there are other tables called “students” (which includes all current and past students) and “schedule” (which holds student schedules). In the schedule table, a column called “s_year” that holds the academic year (in the format of “2017-18”). We can join these tables based on user account IDs in the UserAccount table, the parentID column in the students table, and the student id (s_id) column in the schedule table.

One more thing: Since this list also includes people who have never had students there, the revised query will have to take that into account.

database diagram showing table relationships

The below query will not only solve this problem, but will also sort by first and last name. Users with no academic year (a NULL value) will be at the bottom of the list.

SELECT DISTINCT ua.*, sc.s_year FROM UserAccounts ua 
LEFT OUTER JOIN students s ON s.parentID = ua.ID 
LEFT OUTER JOIN schedule sc ON sc.s_id = s.ID 
WHERE sc.s_year IS NULL 
OR sc.s_year = (
   SELECT MAX(sc2.s_year) FROM schedule sc2 WHERE sc2.s_id = s.ID
) 
ORDER BY sc.s_year DESC, ua.lastName, ua.firstName

The only remaining thing to do is to add the year column to the GridView and make sure that sorting is enabled.

Solving the ROW-00060 Error When Using SSIS with Oracle

Attunity Oracle Source in SSIS

I have built SSIS packages to load data from one Oracle database to another before, but never had I come across this error until recently:

“ROW-00060: Internal error: [dainsert,16] Source: Oracle Destination: Oracle Error Occurred @ after 403k records.”

Initially, I thought that some constraint had been violated on the destination data source – like an attempt at a NULL value being inserted into a NOT NULL column. I ran the package a few times and noticed that the row count was always in the neighborhood of 400k and that the package had run for hours. I thought it odd that so many rows could be inserted with no problem, and so a double- and triple-checked to make certain that the constraints on the source columns were the same as those on the destination ones.

Though there were no clear cut solutions explaining exactly why this error happens, several different people on different fora mentioned that they had overcome this particular error (at different row counts, not always 400k!) by using a connector from Attunity rather than the one that comes with the Oracle Client. Fortunately, this driver is made to work with SSIS and is distributed by Microsoft. This driver not only works with Oracle, but also with Teradata. Choose the version based on the version of SSIS you are using.

Version 2.0 for SQL 2012
Version 3.0 for SQL 2014
Version 4.0 for SQL 2016

After installing the connector into Visual Studio and restarting VS, you should be able to use it by selecting “Oracle Source” and/or “Oracle Destination” from the SSIS Toolbox.

Attunity Oracle Source in SSIS

After setting up the new source and destination connections, I was able to run the SSIS package to completion, loading over five million rows of data in less than an hour!

%d bloggers like this: