presentations

View on GitHub

Very Very Basic SQL for Koha Reports



Q: What does “SQL” stand form

SQL stands for Structured Query Language.

One way of thinking about it is that SQL is a controlled vocabulary for asking the database questions.

A reference librarian analogy would be that SQL is the language you use to ask reference questions to a database.

Q: What does SQL have to do with Koha?

Koha uses SQL for custom reports. To create a custom report in the Koha staff client, click on Reports, then Create from SQL.

Q: What can you do with a custom report that you can’t do with one of the built-in reports in Koha?

The Statistics wizard, Top lists, Inactive, Other reports, and reports made with the “Create guided report” tool can do a lot, but they have limitations. Particularly the “Created guided report” tool. That tool only offers you a handful of database tables that you can work with and what you can do with them. Custom reports allow you to base reports on any data saved anywhere in the Koha database.

Q: How do I learn about writing SQL

There is a very good general SQL tutorial at W3 Schools

There is also one at Tutorials point

And LinkedIn Learning has a full “SQL for Non-Programmers” course at https://www.linkedin.com/learning/sql-for-non-programmers/how-can-sql-answer-your-data-questions

Q: Cheat sheets

There is a good cheat sheet at https://learnsql.com/blog/standard-sql-functions-cheat-sheet/standard-sql-functions-cheat-sheet-letter.pdf but it is not Koha specific

Special note

The custom report interface in Koha is designed only to read data from Koha – you will not be able to use any SQL commands that create, alter, or delete any data from Koha’s reports module. For this reason you can’t use any of these words when creating an SQL report in Koha:

The most basic report possible

Every custom report you create in Koha is going to start with the word “SELECT”; followed by an asterix (wildcard for “all”); followed by the word “FROM”; followed by the table name.

To stretch the reference librarian analogy further, this query is asking the question “What is the information // in all of the fields // in // this table?”

SELECT
  *
FROM
  tablename

An actual sample that will work in Koha

This is just a sample. It’s not a very useful report.

This question is “What is all of the information in the items table”

Sample 001

SELECT
  *
FROM
  items

A slightly more complex report

This report begins and ends with a “SELECT” and a “FROM tablename” but this time we’re going to choose the fields we want instead of selecting them all with a wildcard.

To use the reference librarian analogy again, this query is asking the question “What is the information // in field1, field2, and field3 // in // this table?”

SELECT
  tablename.field1,
  tablename.field2,
  tablename.field3
FROM
  tablename

An actual sample that will work in Koha

This report begins and ends with a “SELECT” and a “FROM tablename” but this time we’re going to choose the fields we want instead of selecting them all with a wildcard.

Sample 002

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items

Adding constraints

We can add “WHERE tablename.fieldname = ‘X’”

This updates the question to “What is the information // in field1, field2, and field3 // in // this table // if field1 matches X?”

SELECT
  tablename.field1,
  tablename.field2,
  tablename.field3
FROM
  tablename
WHERE
  tablename.field1 = "X"

An actual sample that will work in Koha

This report begins and ends with a “SELECT” and a “FROM tablename” but this time we’re going to choose the fields we want instead of selecting them all with a wildcard.

Sample 003

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE
  items.itemnumber = 1

Constraints besides equals

There are different types of basic constraints when working with numeric values:

These questions fit our analogy like “What is the information // in field1, field2, and field3 // in // this table // if field1 (matches is less than is greater than etc. etc.) X?”
SELECT
  tablename.field1,
  tablename.field2,
  tablename.field3
FROM
  tablename
WHERE
  tablename.field1 = "X"

Actual samples that will work in Koha

This report begins and ends with a “SELECT” and a “FROM tablename” but this time we’re going to choose the fields we want instead of selecting them all with a wildcard.

Sample 004

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE
  items.itemnumber < 100

Sample 005

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE
  items.itemnumber > 100

Sample 006

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE
  items.itemnumber <= 100

Sample 007

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE
  items.itemnumber >= 100

Sample 008

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE
  items.itemnumber <> 100

Sample 009

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE
  items.itemnumber != 100

Sample 010

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE
  items.itemnumber BETWEEN 100 AND 150

Constraint is not

You can also use WHERE NOT to constrain the results to anything except a specific match. This works a lot like WHERE <> or WHERE !=

These questions fit our analogy like “What is the information // in field1, field2, and field3 // in // this table // if field1 is not (matches is less than is greater than etc. etc.) X?”
SELECT
  tablename.field1,
  tablename.field2,
  tablename.field3
FROM
  tablename
WHERE NOT
  tablename.field1 = "X"

Actual samples that will work in Koha

Sample 011

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE NOT
  items.itemnumber = 100

Adding multiple constraints

We can also add multiple constraints using AND or OR

SELECT
  tablename.field1,
  tablename.field2,
  tablename.field3
FROM
  tablename
WHERE
  tablename.field1 = "X" AND
  tablename.field2 = "Y"

OR

SELECT
  tablename.field1,
  tablename.field2,
  tablename.field3
FROM
  tablename
WHERE
  tablename.field1 = "X" OR
  tablename.field2 = "Y"

OR

SELECT
  tablename.field1,
  tablename.field2,
  tablename.field3
FROM
  tablename
WHERE
  tablename.field1 = "X" AND NOT
  tablename.field2 = "Y"
SELECT
  tablename.field1,
  tablename.field2,
  tablename.field3
FROM
  tablename
WHERE
  tablename.field1 = "X" OR NOT
  tablename.field2 = "Y"

Actual samples that will work in Koha

Sample 012

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE NOT
  items.itemnumber = 100 AND
  items.biblionumber = 50

Sample 013

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE NOT
  items.itemnumber = 100 OR
  items.biblionumber = 50

Sample 014

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE NOT
  items.itemnumber = 100 AND NOT
  items.biblionumber = 50

Sample 015

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE NOT
  items.itemnumber = 100 OR NOT
  items.biblionumber = 50

These samples are just examples

Don’t limit yourself, either, to what you see in these sample reports. All of the previous several examples are using constraints on two separate fields - itesm.itemnumber and items.biblionumber.

There’s nothing to say you can use multiple constraints on the same field like:

Sample 016

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE NOT
  items.itemnumber = 100 OR
  items.itemnumber = 50

Sample 017

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE NOT
  items.itemnumber = 100 OR NOT
  items.itemnumber < 500

Ordering the results

The next thing I’ll throw in is ordering the results.

The command for this is “ORDER BY” and then you have the option to sort ascending (ASC) or descending (DESC). The default sort order is ASC

To stretch the reference librarian analogy further, this query is asking the question “What is the information // in field1, field2, and field3 // in // this table // if field1 is not (matches is less than is greater than etc. etc.) X; and show me the data in a certain order?”

Sample 018

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE NOT
  items.itemnumber < 100 OR
  items.itemnumber > 1000
ORDER BY
  items.barcode

Sample 019

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE NOT
  items.itemnumber < 100 OR
  items.itemnumber > 1000
ORDER BY
  items.barcode ASC

Sample 020

SELECT
  items.itemnumber,
  items.biblionumber,
  items.barcode
FROM
  items
WHERE NOT
  items.itemnumber < 100 OR
  items.itemnumber > 1000
ORDER BY
  items.barcode ASC

Mixing up the ordering

And you can sort with multiple fields the results with some fields ascending and some fields descending

For this sample, I’m going to switch up tables:

Sample 021

SELECT
  biblio.biblionumber,
  biblio.author,
  biblio.title
FROM
  biblio
WHERE
  biblio.biblionumber < 200
ORDER BY
  biblio.author DESC,
  biblio.title ASC

Counting

A very common and very basic thing that many Koha libraries want to do with reports is to count things. The most basic count is to count all of the rows in a set of results.

This query is very basic and asks the question “What is the result // if I count all the rows // in // this table?”

Sample 022

SELECT
  Count(*)
FROM
  biblio

Counting and grouping

Counting the rows in a table can get you some data, but it’s usually more useful to group results based on the data in a specific field.

This query asks the question “What is the result // if I count all of the rows // in this table // and group them by the author’s name?”

Sample 023

SELECT
  biblio.author,
  Count(*)
FROM
  biblio
GROUP BY
  biblio.author

Joining tables

So far, everything I’ve shown you deals with one table at a time. It’s a lot more useful when you’re writing reports in Koha if you can get data from multiple tables at the same time.

The command for this is “JOIN”

This query asks the question “What is the information // in table1.field1 and table2.field1 // in this table when it’s joined to this other table?”

Sample 024

SELECT
  biblio.author,
  biblio.title,
  items.barcode
FROM
  biblio JOIN
  items ON items.biblionumber = biblio.biblionumber

Joining tables

There are several different types of JOINs you can use in SQL:

For the purposes of Koha, you really only need to know JOIN and LEFT JOIN

This query asks the question “Show me all of the information // in table1.field1 and table2.field1 // in this table when it’s joined to this other table // even if there’s no connection between the tables?”

Sample 025 LEFT JOIN

SELECT
  branches.branchcode,
  Count(items.itemnumber) AS Count_itemnumber
FROM
  items LEFT JOIN
  branches ON branches.branchcode = items.homebranch
GROUP BY
  branches.branchcode

Sample 026 LEFT JOIN

SELECT
  branches.branchcode,
  Count(items.itemnumber) AS Count_itemnumber
FROM
  branches LEFT JOIN
  items ON items.homebranch = branches.branchcode
GROUP BY
  branches.branchcode