1 of 29

Basic SQL for Koha Users

Jason Robb & Christopher Brannon

Monday, April 6th, 2020 @ 8:30 PT / 9:30 MT / 10:30 CT / 11:30 ET

2 of 29

What is SQL?

  • Structured Query Language
  • Relational databases
  • Flavors = terms to add to your Google searches
    • MySQL
    • MariaDB
  • Queries from the Koha staff client are Read Only

3 of 29

Available resources

4 of 29

Understanding the Schema

  • Tables & Fields
  • Keys�
  • Most-used tables
    • Patron info ---> borrowers
    • Fines info ---> accountlines
    • Circulation stats ---> statistics
    • Item data ---> items
    • Bibliographic data ---> biblio
    • Holds ---> reserves
    • Transfers ---> branchtransfers�
  • Tables to avoid (at least at first!)
    • action_logs

5 of 29

Basic Keywords

  • Keywords are used to perform different actions
    • SELECT : pick fields
    • FROM : pick tables
    • JOIN : add more tables
    • WHERE + AND : filter data
    • ORDER BY : sort data

6 of 29

Getting started

  1. Ask a question, have your end result in mind
  2. Determine which tables to use
  3. Start broad, then narrow down
  4. Add usability (links, limits, sorting)
  5. Test and retest - does the data seem accurate?

7 of 29

Building a Basic Query

  • SELECT
  • FROM
    • Demo table dump
  • WHERE
    • Static (find a specific item or borrower)
    • Select SELECTs
    • AND

8 of 29

Parameters

Parameters are formatted with the hungry alligators: <<parameter>>

You can define a label for the parameter using the alligators with a pipe: <<Choose Library|branches>>

Parameters can also be selectable by using:

  • Any authorized value list
  • Library/Branch: branches
  • Shelf Location: LOC
  • Item Type: itemtypes
  • Collection Code: CCODE
  • Lost Status: LOST
  • Not for Loan Status: NOT_LOAN
  • Withdrawn Status: WITHDRAWN
  • Damaged Status: DAMAGED
  • Patron Category: categorycode
  • Pop-up Calendar: date

9 of 29

Adding other tables

  • Joins
    • Diagram
    • Usually start with a LEFT JOIN
    • Biblio and items

10 of 29

Example: LEFT JOIN w/USING

SELECT COUNT(s.datetime) AS count

FROM statistics s

LEFT JOIN items i USING (itemnumber)

WHERE s.datetime BETWEEN <<Between (yyyy-mm-dd)|date>> AND <<and (yyyy-mm-dd)|date>> AND i.homebranch = <<Owning Library|branches>> AND s.type IN ('renew')

11 of 29

Example: LEFT JOIN w/ON

SELECT COUNT(s.datetime) AS count

FROM statistics s

LEFT JOIN items i ON (s.itemnumber = i.itemnumber)

WHERE s.datetime BETWEEN <<Between (yyyy-mm-dd)|date>> AND <<and (yyyy-mm-dd)|date>> AND i.homebranch = <<Owning Library|branches>> AND s.type IN ('renew')

12 of 29

Organizing

  • Order
    • What?
    • How?
      • ASC or DESC
    • Order by Multiple Columns

13 of 29

Example: ORDER BY (Single)

SELECT b.branchcode,b.surname,b.firstname,b.cardnumber,b.categorycode

FROM borrowers b

WHERE b.categorycode='STAFF'

ORDER BY b.branchcode ASC

14 of 29

Example 1: ORDER BY (Multiple)

SELECT b.branchcode,b.surname,b.firstname,b.cardnumber,b.categorycode

FROM borrowers b

WHERE b.categorycode='STAFF'

ORDER BY b.branchcode,b.surname,b.firstname ASC

15 of 29

Example 2: ORDER BY (Multiple)

SELECT b.branchcode,b.surname,b.firstname,b.cardnumber,b.categorycode

FROM borrowers b

WHERE b.categorycode='STAFF'

ORDER BY b.branchcode DESC,b.surname ASC,b.firstname ASC

16 of 29

Useful tactics

  • Aliases
    • items i, biblio b, borrowers p
    • Joining the same table multiple times (authorised_values)
      • authorised_values av1, authorised_values av2, etc.
  • Date range filters
    • BETWEEN <<Date|date>> AND <<and|date>>
  • Concatenation
    • CONCAT / CONCAT_WS
      • Links
      • Statuses
      • Names

17 of 29

Example: BETWEEN

SELECT COUNT(s.datetime) AS count

FROM statistics s

LEFT JOIN items i ON (s.itemnumber = i.itemnumber)

WHERE s.datetime BETWEEN <<Between (yyyy-mm-dd)|date>> AND <<and (yyyy-mm-dd)|date>> AND i.homebranch = <<Owning Library|branches>> AND s.type IN ('renew')

18 of 29

Example: Concat / Concat_WS

SELECT CONCAT_WS(', ',p.surname,p.firstname) AS 'Patron',CONCAT('<a href="http://staff.cin.bywatersolutions.com/cgi-bin/koha/members/memberentry.pl?op=modify&borrowernumber=',p.borrowernumber,'" target="_blank">',p.cardnumber,'</a>') AS 'Library Card'

19 of 29

GROUP BY

  • Counts vs. Lists�
  • Good for categorized summaries
    • Circulation in a category
    • Item count in a category�
  • Keywords for grouping
    • SELECT COUNT( )
    • SELECT SUM( )
    • GROUP BY
    • HAVING

20 of 29

Example: Circulation by collection code

SELECT a.lib AS Collection, COUNT(*) AS 'Checkouts and Renewals'

FROM statistics

LEFT JOIN authorised_values a ON (statistics.ccode=a.authorised_value)

WHERE type in ('issue','renew')

AND datetime BETWEEN <<Find stats between|date>> AND <<and|date>>

AND branch = <<Choose Library|branches>>

GROUP BY ccode

21 of 29

HAVING

  • WHERE is used to filter rows before grouping
  • HAVING is used to exclude records after grouping

Examples

  • Only show records that have more than X items
  • Find records with more than X holds
  • Identifying possible duplicates

22 of 29

Example: Fine free branches

SELECT branchcode, SUM(fine) AS totalfines

FROM issuingrules

GROUP BY branchcode

HAVING totalfines = 0

23 of 29

Unions

  • Info from items and deleted items
  • Info from borrowers and deleted borrowers

24 of 29

Example

SELECT cardnumber, surname, firstname, dateenrolled

FROM borrowers

WHERE dateenrolled > <<Minimum date|date>>

25 of 29

Example

SELECT cardnumber, surname, firstname, dateenrolled

FROM borrowers

WHERE dateenrolled > <<Minimum date|date>>

UNION

SELECT cardnumber, surname, firstname, dateenrolled

FROM deletedborrowers

WHERE dateenrolled > <<Minimum date|date>>

26 of 29

Querying Marc Data (Tag with all subfields)

SELECT ExtractValue(metadata,'//datafield[@tag="952"]/*') AS ITEM

FROM biblio_metadata

WHERE biblionumber=14;

27 of 29

Querying Marc Data (Tag with specific subfield)

SELECT ExtractValue(metadata,'//datafield[@tag="260"]/subfield[@code="b"]') AS PUBLISHER

FROM biblio_metadata

WHERE biblionumber=14;

28 of 29

Querying Marc Data (Specific tag from multiple instances)

SELECT ExtractValue( metadata, '//datafield[@tag="856"][1]/subfield[@code="u"]' ) AS '856$u'

FROM biblio_metadata

WHERE biblionumber=14;

29 of 29

Practicing with SQL