It’s the thing that we keep saying — in order to deal with our masses of stuff better, we need better ways of understanding what we have. A lot of my questions aren’t just about what’s in our finding aids — they’re about the relationships between archival materials and other archival management functions — accessioning, digital object management, location management, container management. For instance, the following questions have come up in the past or could easily come up in the future:
- Which collections are constituted of accessions that came in before 1980?
- Which collections have digital objects associated with them? What are the URIs of those digital objects?
- I have a barcode for a box. Can you tell me the materials that are supposed to be in that box? What collection is this from?
- We haven’t used this location listed in the location table since 2005! Are there any boxes associated with that location? What are they?
In order to answer these questions, I need to write reports that join different tables in Archivists’ Toolkit together. And this is a little bit tricky, because in their own way, components in the AT database are hierarchical (just like in an EAD-encoded finding aid). If I have an instance (a container with a barcode), and I want to know which collection it belongs to, I don’t have a direct relationship in the database. Instead, an instance is associated with a component. That component is associated with its parent component. It may have a lot of ancestor components before the most high-level component is associated with the collection-level information in the resource table.
These relationships are made in sql through what are called “joins”. And joining a table on itself (in some cases several times, recursively) is a huge friggin pain in the neck. So, after mucking around for a little while, the solution was to just ask someone smarter than me how he would handle this.
This is where my colleague Steelsen comes in — Steelsen introduced the idea of writing a stored procedure that would look for the top-most component instead of having to do this through joins. And then he wrote them for me, because he is a mensch of the first order. His procedures are here, and available to anyone who might find them useful. They have seriously revolutionized the way that I’ve been able to do reporting and solve problems.
For instance, something that folks have been begging for is a barcode look-up tool — they have a barcode, and they want to know which collection it belongs to, what its call number is, which location it’s assigned to, and which components are associated with that box. So here’s what I wrote (the user indicates the barcode in the where statement):
use schema; SELECT CONCAT(r.resourceIdentifier1, ' ', LPAD(r.resourceIdentifier2, 4, '00')) 'Collection', r.title 'Collection Title', series.subdivisionIdentifier 'Series/Accession Number', series.title 'Series Title', rc.title 'Component Title', rc.dateExpression 'Component Date', adi.container1Type 'Container Type', adi.container1NumericIndicator BoxNum, adi.container1AlphaNumIndicator BoxAlpha, adi.container2NumericIndicator FolderNum, adi.container2AlphaNumIndicator FolderAlpha, adi.archDescriptionInstancesId InstanceID, adi.barcode Barcode, adi.userDefinedString1 'Voyager Info', loc.LocationId, loc.building, loc.room, loc.coordinate1NumericIndicator ShelfNum, loc.coordinate1AlphaNumIndicator ShelfAlpha FROM ArchDescriptionInstances adi INNER JOIN ResourcesComponents rc ON adi.resourceComponentId = rc.resourceComponentId INNER JOIN LocationsTable loc ON adi.locationID = loc.locationID INNER JOIN Resources r ON r.resourceId = GETRESOURCEFROMCOMPONENT(rc.resourceComponentId) LEFT OUTER JOIN ResourcesComponents series ON GETTOPCOMPONENT(rc.resourceComponentId) = series.resourceComponentID WHERE adi.barcode = 39002042658774;
Here I use two of Steelsen’s procedures. In GETRESOURCEFROMCOMPONENT, I go up the tree of a component to find out what resource it belongs to and join that to the resource. I use GETTOPCOMONENT to help figure out what series a component belongs to (this assumes that the top-most component is a series, but that’s usually a safe bet for us).
I’m a sql n00b, and this isn’t the most efficient query I’ve ever run, but I’m really happy with the results, which can be viewed in a spreadsheet here.
By changing the where statement, I can find out all kinds of associated information about a location, a collection, a box, whatever. I can find out if barcodes have been assigned to components with different box numbers; I can find out if components with the same barcode have been assigned to more than one location. This set of procedures has really been a godsend to help me know more about the problems I’m fixing. So many thanks to Steelsen. I hope others find them useful too.