You are on page 1of 51

Introduction to Access SQL

Practical workbook

Aims and Learning Objectives


By the end of this course you will be able to: use Access SQL instead of or in addition to standard queries; understand the importance and usefulness of a knowledge of SQL.

University of Bristol Information Services document acc-8

Introduction to Access SQL(acc-8)

Document information Format conventions


The following format conventions are used in this document: Computer input that you type is shown in a bold Courier font Computer output, menu names and options, buttons, URLs are shown in a Courier font Text that you must replace is shown in italics Computer keys that you must press are in a bold Courier font and enclosed in angle brackets Instructions for users of other software versions are displayed in a boxed area. http://www.bristol.ac.uk Save, Go to, Refresh Enter your username <Enter>, <n>, <N>, </> Example text like this

Course files
This document and any associated practice files (if needed) are available on the web. To find these, go to www.bristol.ac.uk/is/learning/resources and in the Keyword box, type the document code given in brackets at the top of this page.

Related documentation
Other related documents are available from the web at: http://www.bristol.ac.uk/is/learning/resources

Introduction to Access SQL (November 05) 2010 University of Bristol. All rights reserved.

Contents
Format conventions Related documentation Task 1 SQL commands ............................................................................... 1 Example database ........................................................................... 1 Looking at the SQL of a query ...................................................... 2 Looking at the SQL of a table lookup box .................................... 2 Looking at the SQL of a form combo box or listbox.................... 3 Looking at the SQL of a graph ...................................................... 3 Query using the Sort option and Top Values ............................... 4 Create SQL from scratch ............................................................... 4 Minimum SQL- list all fields of a single table .............................. 4 Query to list all fields of a single table and specify sort order .... 5 Unique Records ............................................................................... 6 Top Records ..................................................................................... 6 Unique values .................................................................................. 7 Create your own query using SQL only........................................ 7 Simple selection criteria.................................................................. 8 Query using selection criteria on different types of data ............. 8 Using criteria in different fields with the or operator .................. 9 Query using criteria in the same field with the or operator ...... 10 Expressions and functions ............................................................ 12 Query using arithmetic ................................................................. 12 Aggregates on groups of records ................................................. 14 Calculation on a group ................................................................. 14 Setting criteria on aggregate queries ........................................... 15 Creating a query using multiple tables ....................................... 17 Query using two linked tables ...................................................... 17 Query using three linked tables ................................................... 19 Using SQL Specific in a Query .................................................... 20 Create your own query ................................................................. 21

Task 2

Task 3

Task 4 Task 5

Task 6

Task 7

Introduction to Access SQL(acc-8)

Further examples of SQL ........................................................................................ 22 Task 8 More criteria.................................................................................. 23 Query showing the use of the > operator .................................... 23 Query showing the use of the between operator ......................... 23 Query using Like ........................................................................... 23 Testing for unknown values ......................................................... 25 Creating a parameter query......................................................... 26 Prompted query............................................................................. 26 Create your own query using SQL only...................................... 26

Task 9

Task 10 Action queries ................................................................................ 27 Task 11 The iif function .............................................................................. 28 Using iif .......................................................................................... 28 Group iif ......................................................................................... 28 Task 12 Crosstab Query ............................................................................. 30 Task 13 Date handling ................................................................................ 32 Date format .................................................................................... 32 Date functions ................................................................................ 32 Age calculation .............................................................................. 32 Task 14 Define your own group values...................................................... 34 Task 15 Queries within queries .................................................................. 36 Nested query .................................................................................. 36 Task 16 Calculating percentages ................................................................ 37 Task 17 Unmatched query .......................................................................... 39 not exists operator ......................................................................... 40 not in method ................................................................................. 40 Task 18 Creating tables............................................................................... 41 Task 19 Table Constraints .......................................................................... 42 Task 20 Create an index.............................................................................. 43 Appendix A SQL syntax .................................................................................... A-1 Standard SQL select statement ................................................. A-1 Access SQL syntax ..................................................................... A-1 Delete statement ......................................................................... A-2 INSERT command ..................................................................... A-2 UPDATE command ................................................................... A-2 Data dictionary .............................................................................. B-1

Appendix B

Introduction
This document describes the SQL (Structured Query Language) generated by Microsoft Access when using the QBE interface. By looking at different types of queries, you can teach yourself SQL. This document describes the purpose of each SQL clause and how it all fits together. Although most of the time the user need not be exposed to SQL in Access, it can be useful to understand the structure of SQL and when it generates clauses and extra brackets unexpectedly. It is also useful to know how Access SQL differs from standard SQL, in case you are transferring the database to another package such as Oracle. Knowing about SQL in Access is useful when: Looking at the source of a combo box. As the source is given in SQL, you could also change the ordering or add a conditional clause. Looking at the source of a graph. As the source is given in SQL, you also could add a conditional clause or copy a graph, and change the base table or query. A query is not doing what is expected. You want to create similar queries based on different tables or update a query when the table name has been changed. It can be easier to copy the original query, and change the name of the table using the SQL view. You want to do a union query. This is a special type of query that can only be constructed if you know SQL.

Prerequisites
You should have attended the course Using and designing Access databases (CC1ACC). This course is based on a thorough understanding of the query types learned on those two courses.

Introduction to Access SQL(acc-8)

Task 1 SQL commands


Objectives Comments
To show where SQL is used. SQL commands are used to create, query and maintain a database. A query can contain only a single SQL command. The command is terminated by a semicolon. Retrieving data from the database to display is the most common SQL operation, and to perform this the select command is used. The basic select command consists of two clauses (sections) which must be specified in the correct order: select the data (field names or expressions) to display from a table or tables from where the data comes. The select clause is always entered first, and is immediately followed by the from clause. It can also specify conditions for selecting records, ordering, grouping and joins between tables. A full list of SQL clauses is given at the end of this document. The maximum length of an SQL statement in Access is 64,000 characters. SQL has been available since Access version 1.

Example database
Open the database C:\Training\Access\SQL\Treatment for SQL. This example database has the following 5 tables: Patients; Drugs; Doctors; Treatment; Diagnosis

Figure 1 relationships

The data consists of details of each patient (date of birth, sex etc), doctor, drugs available and details of treatment. The patients are identified by a reference number (PatientID). By splitting the data like this, duplication of details such as drug name is avoided. The queries used are the same as those in Making more of queries (document acc23) and the same type as those demonstrated on the course Using and Designing Access databases (document acc2).
Introduction to Access SQL (acc-8) 1

Introduction to Access SQL(acc-8)

Looking at the SQL of a query


1.1 From the Navigation pane, Open a query in design view . Click Queries, then click the Design button (as shown opposite). Click on SQL view.

Looking at the SQL of a table lookup box


1.2 Open a table in design view. (right click) Select a field that has a lookup attached to it. For example, if you are using the treatments example database, look at the PatientID field of the Treatment table. Press the lookup tab below the list of fieldnames. Look at the Row source Property. SELECT [Patients].[PatientID], [Patients].[Given name], [Patients].[Family name] FROM [Patients];

Introduction to Access SQL (acc-8)

Introduction to Access SQL(acc-8)

Looking at the SQL of a form combo box or listbox


1.3 Open a form in design view (Combo 2 autolookup in the treatment database). Select the field that has a lookup attached to it. Show the data properties by using the properties icon, right-click the field and selecting properties, or selecting properties from the View menu. 1.4 Look at the Row source Property. SELECT DISTINCT ROW DrugID, [Drug Name] FROM Drugs ORDER BY [Drug Name];

Open the Patients form in form view. Look at the dropdown box for the doctor for several patients. Only doctors of the same gender as the patient are displayed. Look at the design view of the form and at the Row Source Property of doctor: SELECT [Doctors].[DoctorID], [Doctors].[Family name], [Doctors].[Given name], [Doctors].[Initials], [Doctors].[Title], [Doctors].[Internal telephone], [Doctors].[gender] FROM [Doctors] where gender=Forms!Patients!gender order by [family name]

Note that the semi-colon at the end of the SQL statement is optional on a form, but compulsory on a query or in a module and indicates the end of the query. It is good practise to always include it if in doubt.

Looking at the SQL of a graph


1.5 Open a chart form in design view (for example the drug pie chart in the treatment example database). Click on the graph and select the data properties. Look at the Row source Property: SELECT [Drug name], SUM([all_info].[Treatment].[PatientID]) AS [Treatment_PatientID] FROM [all_info] GROUP BY [Drug name];

Introduction to Access SQL (acc-8)

Introduction to Access SQL(acc-8)

Task 2 Query using the Sort option and Top Values


Objectives Comments
To understand the basic structure of a simple SQL statement. By looking at the SQL of a query which has been created using the normal grid method, one can see how modifying the query affects the SQL. One can specify which columns of data one wants to see and in what order, and one can specify the order of the rows. The select, from and order by clauses will be described.

Create SQL from scratch


2.1 Create a new query but close the Show table box without choosing a table. Look at the SQL by using the SQL button on the left of the toolbar. You will see: SELECT; You can now type the SQL yourself. However, you will have the problem that you need to know the names of the fields and tables and that you must get the syntax right. You will not be able to go back to the grid until the syntax is correct and you may not understand the warning message. If you get the field names or table names wrong you should be able to go back to the grid, but wrong field names will be shown as expressions, and wrong table names as tables with no fields.

Minimum SQL- list all fields of a single table


2.2 Create a select query using design view to list all the details of all the patients. Field Table Sort Show Criteria 2.3 Look at the SQL: SELECT Patients.* FROM Patients; SQL is case-insensitive- it does not matter whether it is typed in upper or lower case; the SQL select command is used to display data. Patients.* Patients

Introduction to Access SQL (acc-8)

Introduction to Access SQL(acc-8)

An SQL select command can have many clauses - which must be specified in a particular order (see the syntax at the end of this document). As a minimum, it must specify which fields are to be selected from which tables: The select clause specifies the fields or expressions to be displayed (the fields are separated by commas; * means all fields) and the from clause specifies which table(s) they are to be taken from. The field name will appear in the select clause only if Show is ticked in the query design. SQL commands can continue over more than one line in a query. They are terminated by a semicolon in a query. Fieldnames and tablenames which include a space or arithmetic operator etc, will have the name enclosed by square brackets to show where the name begins and ends. The fieldnames are preceded by the tablename by default, for example Patients.*, Patients.[Family name]. In actual fact, the field names only need to prefixed by the table name if the same field name appears in a query involving more than one table and the name of the field is in both tables.

Query to list all fields of a single table and specify sort order
2.4 Create a query using the normal grid as follows: (Open the query Example 02a) Create a query to list all the details of all the patients in ascending order of family name (add the family name field as a no show field since it is already being shown): Field Table Sort Show Criteria Save your query. 2.5 Look at the SQL: SELECT Patients.* FROM Patients ORDER BY Patients.[Family name]; The order by clause specifies which fields govern the order in which the records are displayed. By default order by gives ascending order. See what happens to the SQL when you specify descending order. Patients.* Patients Family name Patients Ascending

Introduction to Access SQL (acc-8)

Introduction to Access SQL(acc-8)

The asc and desc operators specify whether the ordering is ascending or descending. The default is asc. The order by clause is always the last clause. Note the square brackets around [Family name] since it contains a space. Square brackets are used to determine field names and table names, for example, [Date of Birth] since including spaces and operators is .allowed for names (but not advisable!)

Unique Records
2.6 Look at the properties of the query by right-clicking the area where the tables are displayed. By default, Unique Records and Unique Values are both set to No. Change Unique Records to Yes. 2.7 Look at the SQL: SELECT Distinctrow Patients.* FROM Patients ORDER BY Patients.[Family name]; DISTINCTROW has been added to the select clause. Note that DISTINCTROW may be added automatically to the SQL (particularly in combo boxes). This indicates that data based on duplicate entire records will not be displayed more than once, but data duplicated on just the selected fields will. In practice, if one has set a primary key, there will be no duplicate records. For example, if one is just displaying the gender field, m and f will be displayed as many times as there are patients. Task 2.11 shows how to display distinct values on selected fields (just show m and f once).

Top Records
2.8 Select the first 5 patients by clicking on the design button to return to the query design window, then use the dropdown box on the Top Values button (the All button on the toolbar) to select the first 5 patients. (By default, the defaults value shown is All). Look at the SQL: SELECT DISTINCTROW TOP 5 Patients.* FROM Patients ORDER BY Patients.[Family name]; Notice that in the query design, the dropdown box gave the option of looking as 5, 25, 100, 5%, 25% or All. By modifying the SQL directly you can specify the exact number you wish to see.

2.9

Notice the TOP descriptor in the SQL and alter the SQL to look at the first 7 patients. In the query design, select the first 5% of the patients, by using the Top Values button on the grid toolbar.

Introduction to Access SQL (acc-8)

Introduction to Access SQL(acc-8)

2.10

Look at the SQL: SELECT TOP 5 PERCENT Patients.* FROM Patients ORDER BY Patients.[Family name]; Notice the PERCENT descriptor used in conjunction with the TOP descriptor. Save the query.

Unique values
2.11 Find the different towns that patients come from: Field Table Sort Show Criteria Change the property of the query for Unique Values to Yes 2.12 Look at the SQL: SELECT DISTINCT Patients.Town FROM Patients; DISTINCT displays unique values of the fields being displayed (more useful than Distinctrow). Open the query and show the SQL you created in Task 2.10 and copy it. Open Notepad, paste in the SQL and change all occurences of Patients to Doctors. Paste the new SQL back into the query and run. The above shows how a knowledge of SQL can help you to create similar queries on different tables. This is much easier than rebuilding the query. Town Patients

Create your own query using SQL only


Before you do this, open the Drugs table and note down the field names. Check each part you create in SQL, in the design and datasheet views as you go. List all the drugs in descending order of Tablets per packet. Show the top 6 drugs.

Introduction to Access SQL (acc-8)

Introduction to Access SQL(acc-8)

Task 3 Simple selection criteria


Objectives
To understand how SQL is used to restrict the rows selected for which the given conditions are true. This task demonstrates the SQL when criteria must be satisfied on different types of data. Rows of data are included (or excluded) by the use of the SQL where clause of the select statement. When more than one criterion is give, the Boolean operators and and or are needed to separate the criteria and to state whether some or all of the criteria must be true. Round parentheses must be used to indicate order of precedence, particularly when and and or conditions are used together. # and " also appear in SQL to show the type of constant. The Criteria and Or field options are used to specify whether you want the query to include or exclude information based on the contents of a field. Note that Access inserts hashes (#) around dates - this confirms that Access recognises them as date strings. Quotes are automatically placed around the text strings. Numeric criteria do not have quotes or hashes around the number. Field names are enclosed by square brackets.

Comments

Boolean Operators
You will see the use of some of the following Boolean operators: And Combines expressions. For the combined expression to be true, each of the component expressions must be true. Lastname="Smith" and Firstname="Jane"

Or

Combines expressions. For the combined Lastname="Smith" or expression to be true, any one of the component Lastname="Jones" expressions must be true. Combines expressions. For the combined expression to be true, only one of the component expressions must be true. Lastname="Smith" xor Firstname="Jane"

XOr

Query using selection criteria on different types of data


3.1 Find the female patient born on 22 November l942 whose ID is less than or equal to 10: (Open the query Example 03a) Field Table Sort Show Criteria <=10 "f" #22/11/42# PatientID Patients Title Patients Family name Gender Patients Patients Date of Birth Patients

Introduction to Access SQL (acc-8)

Introduction to Access SQL(acc-8)

3.2

Look at the SQL: SELECT DISTINCTROW Patients.PatientID, Patients.Title, Patients.[Family name], Patients.Gender, Patients.[Date of Birth] FROM Patients WHERE (((Patients.PatientID)<=10) AND ((Patients.Gender)="f") AND ((Patients.[Date of Birth])=#11/22/42#)); A where clause is included in the select command after the from clause to choose only records which fit specified criteria. The and operator between two criteria means both criteria must be true. If no operator is given in the where criteria grid, then "=" is used. You can use <, <=, >, >= , <> and "between..and.." on text, date and numeric fields. Text searches are not case sensitive. Quotes are placed automatically round text to be searched (double by default but one can use single quotes). Date values need to be surrounded by #. This enables the user to type the date in whatever format is most familiar and it will then be converted into a form that Access can handle. Numeric criteria do not need quotes or a hash around the number. Round brackets (most are unnecessary) are used around each where condition to determine order of precedence, and around functions, for example, avg(Fees).

Note

Access has a habit of adding large numbers of brackets.

Using criteria in different fields with the or operator


3.3 Find patients who live in Bristol or who are female: (Open the query Example 03b) Field Table Sort Show Criteria Or "Bristol" "f" Given name Patients Family name Patients Town Patients Gender Patients

Introduction to Access SQL (acc-8)

Introduction to Access SQL(acc-8)

3.4

Look at the SQL: SELECT Patients.[Given name], Patients.[Family name], Patients.Town, Patients.Gender FROM Patients WHERE (((Patients.Town)="bristol")) OR (((Patients.Gender)="f")); The or operator includes all entries where one or the other (or both) of the conditions is true. Round parentheses must be used to indicate order of precedence particularly when and and or conditions are used together. For example, to find males from Bristol and females from Bath. (Patients.Town="bristol" and gender="m") OR (Town="Bath" and Patients.Gender="f")

Query using criteria in the same field with the or operator


3.5 Find patients who live in Bristol or Bath: (Open the query Example 03c) Field Table Sort Show Criteria Or 3.6 Look at the SQL: SELECT Patients.[Given name], Patients.[Family name], Patients.Town, Patients.Gender FROM Patients WHERE (((Patients.Town)="bristol")) OR (((Patients.Town)="bath")); Note The grid will automatically change the two criteria if they have been placed on separate fields (since it is the same field) to one criterion on town, but the SQL ends up with more criteria since it can only test one value at a time. It also ends up with more round brackets since it puts them round each criterion field. You could type in ("Bristol","Bath") instead of the two where conditions. (Open the query Example 03d) SELECT Patients.[Given name], Patients.[Family name], Patients.Town FROM Patients WHERE (((Patients.Town) In ("bristol","bath","keynsham"))); The in operator gives a list of possible values for a field. In this example, it is shorter to use in than oring the conditions as above. "Bristol" or "Bath" Given name Patients Family name Patients Town Patients

Introduction to Access SQL (acc-8)

10

Introduction to Access SQL(acc-8)

Create your own query using SQL only


Before you do this open the diagnosis table and note down the field names. It is not necessary to add the brackets in the Where section. List the PatientID and diagnosis for patients suffering from headache OR sickness. Check the query in the design and datasheet views.

Introduction to Access SQL (acc-8)

11

Introduction to Access SQL(acc-8)

Task 4 Expressions and functions


Objectives Comments
Learn how to create expressions and use simple functions, giving the result a sensible name. You can create arithmetic expressions (+, -, * (multiplication) and / (division)) and character expressions (& for concatenation) in SQL. You will see the use of As to identify the name of the calculated field.

4.1

If one of the fields used for multiplying and dividing has a null value then the result of the whole expression will be null.

Query using arithmetic


4.2 Find the cost per tablet of each drug: Cost_per_tablet:[Cost Cost per packet per packet] /[tablets per packet] Drugs

Field Table Sort Show Criteria

Drugname Tablets per packet Drugs >0 Drugs

Look at the SQL: SELECT Drugs.[Drug name], Drugs.[Tablets per packet], Drugs.[Cost per packet], [Cost per packet]/[tablets per packet] AS cost_per_tablet FROM Drugs WHERE (((Drugs.[Tablets per packet])>0)); Arithmetic expressions can be used in the select as well as the where clause. The cost per tablet for each drug is calculated by dividing the cost per packet by the number of tablets per packet. The as clause gives a name to the resulting expression (default expr1 which appears before the : in the grid). Character function 4.3 Display the towns that people come from in capital letters: (Open the query Example 05b) Field Table Sort Show Criteria towns: UCase([Town])

Introduction to Access SQL (acc-8)

12

Introduction to Access SQL(acc-8)

4.4

Look at the SQL: SELECT DISTINCT UCase([Town]) AS towns FROM Patients; The UCase function converts values to upper case. Access changes the name of the function from ucase to UCase but case has no significance so it does not matter how you type it. Remember to name the heading of the field differently to the name of the field otherwise you get a circular alias message.

Note

Use Access query language elements (document acc-r4) to see what other functions are available.

Create your own query using SQL only


Calculate the cost of 10 tablets of each drug, showing drug name, cost per packet, cost per tablet and cost per 10 tablets. Put the drug name in capitals. List the treatments and also show a date one month later than the date of starting the course. List the family name and given name as one value separated by a comma, and the town and postcode as one value separated by a space.

Introduction to Access SQL (acc-8)

13

Introduction to Access SQL(acc-8)

Task 5 Aggregates on groups of records


Objectives Comments
This shows the effect of using the Totals icon in a query. It is possible to create an SQL query that calculates values for each group of records, for example, the number of patients who all come from each town. The group by and having clauses are introduced. To do this you need to specify the fields to use with the group by clause which must match the fields in the select clause as well as the fields to use with the aggregate functions (Sum or Avg for instance).

Calculation on a group
5.1 Find how many patients there are in each town ordered by the biggest population: (Open the query Example 07a) Field Table Total Sort Show Criteria Town Patients Group By Number of Patients: PatientID Patients Count Descending Town Patients Count Descending

Introduction to Access SQL (acc-8)

14

Introduction to Access SQL(acc-8)

5.2

Look at the SQL: SELECT Patients.Town, Count(Patients.PatientID) AS [Number of patients], Count(Patients.Town) AS CountOfTown FROM Patients GROUP BY Patients.Town ORDER BY Count(Patients.PatientID) DESC , Count(Patients.Town) DESC; Note the new group by clause finds the unique values of the fields given in it. The group by clause always follows the where clause if there is one. Since there is no where clause in the example above, then it follows the from clause. The group by field option on the Town field operates with the Count function on the patient ID to divide all the patients into groups based on the town in which they live. Count is then applied to the rows in each group. Note that some patients do not have a town as part of their address. The group by clause must contain the same fields as the select clause, except for the fields that hold aggregates, and in the same order. Thus, in the example, the group is on town, so the select clause and the group by clause both work on the town field to find the unique values of town. The count functions in the select clause then show the counts for each town. Count should be applied on the Primary key (PatientID) to give the number of patients for each town including those patients where the town is unknown. Applying the count on town shows 0 for unknown towns, so if you want to get a count of how many unknown values there are, count on the primary key. The order by clause orders output, in ascending order by default. It is possible to order on a count as well a field. If the field to be ordered has an alias, the alias can be given in the order by clause. The order by clause must follow the group by clause. Note that the order clause has been added because the sort field has been specified on the grid. order is normally the last clause of a select statement (unless the with owner access option has been used or it is a crosstab query). If the grouping is to be done on more than one field, the field specifications are separated by commas.

Setting criteria on aggregate queries


5.3 Find the towns whose name start with B and which have more than 3 patients. Display in order of size: (Open the query Example 07b) Field Table Total Sort Show Criteria Town Patients Group By count: PatientID Patients Count Descending >3 Like "B*" Town Patients Group By Ascending Town Patients Where

Introduction to Access SQL (acc-8)

15

Introduction to Access SQL(acc-8)

5.4

Look at the SQL: SELECT Patients.Town, Count(Patients.PatientID) AS count FROM Patients WHERE (((Patients.Town) Like "B*")) GROUP BY Patients.Town, Patients.Town HAVING (((Count(Patients.PatientID))>3)) ORDER BY Count(Patients.PatientID) DESC , Patients.Town; The new having subclause of the group clause limits the number of groups used. having clause always appears after the group clause and cannot be used without a group by clause. The having criteria should normally be used on the aggregate function fields such as avg, sum etc since it works on the aggregate value not the individual record value unlike the where clause. It is important to distinguish between testing for a field value and an aggregated value. This is demonstrated by the use of the where clause to perform criteria on individual field values, where it is used to filter out records before aggregation, that is towns whose name start with B. The having criteria checks the result of an aggregated function, that is more than 3 patients. Do NOT put town like "B*" in the having clause but in the where clause. Although putting the criteria in the having clause will give the correct answer it is very inefficient since the query has to select all the records before it aggregates them and then filter out the towns not starting with B. Putting the criteria in the where clause makes sure that the non-B records are filtered out before the aggregation is done so it has far less work to do. Town appears in the grid three times because the ordering is done on the count and then the town, but the town was to be displayed first. Town then appears so that the criterion of towns starting with the letter B can be set. Normally one would expect the group fields to reflect the none aggregated fields on the select clause. The SQL is more understable than the grid! Order by can be used on aggregate functions as well as field values. The query Example 07c is another example of this type of query.

Create your own query using SQL only


From the Doctors table count the number of doctors for each title. Order them with the largest number first. From the diagnosis table, count the number of patients seen on each date before 23/04/1996 ordered by date in ascending order.

Introduction to Access SQL (acc-8)

16

Introduction to Access SQL(acc-8)

Task 6 Creating a query using multiple tables


Objectives Comments
SQL can be used to access data from more than one table. Access SQL over more than one table is rather complicated and uses inner join clauses to specify the links. Standard SQL is far more understandable.

Query using two linked tables


6.1 Use the Drugs and Treatment tables to find the cost per day for treatment for each drug: (Open the query Example 09a) Field Table Total Sort Show Criteria [Drug name] Drugs Group By Expression drug_cost: Sum([Dosage]*[cost per packet]*[doses per day])

Introduction to Access SQL (acc-8)

17

Introduction to Access SQL(acc-8)

6.2

Look at the SQL: SELECT DISTINCTROW Drugs.[Drug name], Sum([Dosage]*[cost per packet]*[doses per day]) AS drug_cost FROM Drugs INNER JOIN Treatment ON Drugs.DrugID = Treatment.DrugID GROUP BY Drugs.[Drug name]; When data from more than one table is selected by a query, the tables must be joined using the common linking fields. Note the inner join clause on the drugs table to the treatment table. The inner join clause has come from linking the tables by drawing a line between the two tables. It signifies an equi-join (to only display the combined record if there are matching fields in both records). This is a non-standard SQL clause to link the two tables. The structure of the inner join clause first identifies the two tables to be joined and then gives the joining fields after the on clause. Inner join is part of the from clause so appears before a where clause. If one wanted to use standard SQL, a where condition would be added not by drawing a line between the linking fields, but by using the criteria box instead, for example, in the TREATMENT.DrugID field specification, add the criteria [DRUGS].[DrugID]. This results in a where clause instead of an inner join clause. The where clause must appear after the from clause. You must add the square brackets otherwise Access assumes that you are looking for text and helpfully adds double quotes! From Drugs, treatment where [Drugs].[DrugID] = [Treatment].[DrugID] It is more efficient to specify the join conditions before any other conditions in the where clause. If the field name is unique to a particular table (for example 'Drug name'), the table name need not be specified. If the field name appears in more than one table being queried, it must be prefixed by the table name.

Introduction to Access SQL (acc-8)

18

Introduction to Access SQL(acc-8)

Query using three linked tables


6.3 Find which drugs were taken by which gender: (Open the query Example 09b) Field Table Sort Show Criteria Gender Patients Drugname Drugs Dosage Treatment

6.4

Look at the SQL: SELECT Patients.Gender, Treatment.Dosage, Drugs.[Drug name] FROM Drugs INNER JOIN (Patients INNER JOIN Treatment ON Patients.PatientID = Treatment.PatientID) ON Drugs.DrugID = Treatment.DrugID; In this example, data is selected from the Drugs, Patient and the Treatment tables. In this case the common linking fields are PatientID and DrugID which is shown by the inner join clause. Round brackets identify the joins and it can get really hard to unravel what is being joined to what. Start at the most embedded join (inside the most brackets) - so Patients and Treatments are joined first on PatientId, and then Drugs to Treatment on DrugID. If one wanted to use standard, more understandable SQL, the statement would read: SELECT Patients.Gender, Treatment.Dosage, Drugs.[Drug name] FROM Patients, Drugs, Treatment where [Drugs].[DrugID] = [Treatment].[DrugID] and Patients.PatientID = Treatment.PatientID

Create your own query using SQL only


Find the Family name (from Patients), date seen and diagnosis (from Diagnosis). Adapt the previous query to show also the Drug given (DrugID from Treatments). Using the QBE grid method, add the Treatments table and change the DrugID from Treatments to Drug name from Drugs. Check that it works and then look at the SQL to see how a third inner join works.

Introduction to Access SQL (acc-8)

19

Introduction to Access SQL(acc-8)

Task 7 Using SQL Specific in a Query


Objectives Comments
To create a query using SQL only. SQL can be typed in without creating a query first. You must be aware that converting to a Select query later will mean that the SQL is lost. It cannot be looked at with the grid. SQL specific is really only used when you wants to use SQL to create tables or indexes, send SQL to a non-Access database system or create more complex queries. The most useful SQL specific query in Access is the union query.

7.1

Create a new query in design view and cancel the Add table window. Look at the query types from the Query menu and note the choice of Pass through, data definition or union. Pass-through. This query can return records, be used to change data, create a database object, or perform an action as an action query does. This type of query sends commands directly to ODBC databases, such as Oracle. The SQL must be the same SQL as the database you are using. Thus, if the SQL is being used to query an Oracle database (perhaps because the query cannot be performed using Microsoft Access), then the SQL must be Oracle SQL (which can differ greatly from Microsoft SQL). Data Definition. Use SQL data definition queries to create, delete, or alter tables; or create indicies in the current database, (particularly if you are linking to tables in another database that for example, does not have a primary key). Each data-definition query consists of just one datadefinition statement. Microsoft Access supports these data-definition statements: CREATE TABLE creates a table; ALTER TABLE adds a new field or constraint to an existing table; DROP deletes a table from a database or removes an index from a field or group of fields; CREATE INDEX creates an index for a field or group of fields. Union. This type of query combines fields from two or more queries into a single query. The two select queries must have the same number and type of fields, and the fields must be in the same order. It eliminates duplicate rows. For example, if you have one query that lists individual treatments and another that lists the totals for each drug, you can combine these lists into one result set using a union query.

Introduction to Access SQL (acc-8)

20

Introduction to Access SQL(acc-8)

Open the query Example 11a. This is a union query and combines Diagnosis and Treatment records for each patient, including the doctor details. 7.2 Look at the SQL: SELECT Patients.PatientID, [Patients].[Given name] & " " & [Patients].[Family name] AS patient, [Doctors].[Title] & " " & [Doctors].[Family name] AS doctor, Diagnosis.[Date seen] as date_happening, Diagnosis.diagnosis FROM Patients INNER JOIN (Doctors INNER JOIN Diagnosis ON Doctors.DoctorID = Diagnosis.DoctorID) ON Patients.PatientID = Diagnosis.PatientID UNION SELECT Patients.PatientID, [Patients].[Given name] & " " & [Patients].[Family name] AS patient, [Doctors].[Title] & " " & [Doctors].[Family name] AS doctor, Treatment.[Date start course] as date_happening, Drugs.[Drug name] FROM Doctors INNER JOIN (Drugs INNER JOIN (Patients INNER JOIN Treatment ON Patients.PatientID = Treatment.PatientID) ON Drugs.DrugID = Treatment.DrugID) ON (Doctors.DoctorID = Treatment.DoctorID) AND (Doctors.DoctorID = Treatment.DoctorID) ORDER BY Patients.PatientID, date_happening; Union combines the rows returned by two select statements. It is easier to construct this type of query by creating the first part of the query, then creating the the second, adding the union operator and then copying and pasting the SQL of the first query onto the second. The number of fields in the two select clauses must be the same, and the data types of the selected fields must match. The as clause can be used to change the name of the resulting fields. By default, the resulting field should be the name of the field of the first slect clause. Thus, the last field is called diagnosis, the penultimate field is called date_happening. The last clause is the order by clause. This applies to the result of the whole query, not the integral parts so there is only one ordering clause. Note the new icon for the union query in the database window.

Create your own query


List the names of the patients and the names of the doctors.

Introduction to Access SQL (acc-8)

21

Introduction to Access SQL(acc-8)

Further examples of SQL


The following notes are intended for use as a continuation from Introduction to Access SQL (document acc-t8). They contain further working examples of Access SQL for course participants to explore and use in their own time. The query examples used are contained in the same database as the rest of the course Treatment_SQL.mdb.

Introduction to Access SQL (acc-8)

22

Introduction to Access SQL(acc-8)

Task 8 More criteria


Objectives Comments
This task gives uses of relational operators to test values. You have just seen the use of Boolean operators such as and and or being used when there is more than one condition to be joined. Relational operators such as >, <, in, between and like are used to compare one field value with a value. Relational operators are used to construct selection criteria for queries. Operators are: =, <, <=, <>, Tests for equality >, >= Between Like In Not Is null Is not null Tests whether a value falls within a range >10 <>"A" between 0 and 10

Tests whether the entry in a text field matches a like "Ch*" pattern Tests whether an entry is an item in a set Negates an expression Tests whether a field is empty (used as a selection criterion) Tests whether a field is not empty in (50, 100, 200) in ("Bristol", "Bath") not <100 is null Is not null

Query showing the use of the > operator


Select the drugs which have more than 50 in a packet and the name starts at least with a 'd'. (Open the query Example 04a) 8.1 Look at the SQL: SELECT Drugs.[Drug name], Drugs.[Tablets per packet], Drugs.[Cost per packet] FROM Drugs WHERE (((Drugs.[Drug name])>"d") AND ((Drugs.[Tablets per packet])>50));

Query showing the use of the between operator


8.2 Select the patients whose family name has a given range of character values, who were born in a given date range and whose id is in a given range of numerical values. (Open the query Example 04b)

Query using Like


8.3 Find the patients whose name starts with "m" and postcode starts with B and then any letter between A and S, then a single digit and a space. (Open the query Example 04c)
23

Introduction to Access SQL (acc-8)

Introduction to Access SQL(acc-8)

Field Table Sort Show Criteria 8.4 Look at the SQL:

PatientID Patients

Family name Patients m*

Postcode Patients B[A - S]# *

SELECT Patients.Initials, Patients.[Family name], Patients.Postcode FROM Patients WHERE (((Patients.[Family name]) Like "m*") AND ((Patients.Postcode) Like "B[A-S]#*")); Typing a wild card character such as * introduces the like operator. Access will change the criteria m* to like "m*". Like allows comparisons between strings using wild card characters and so is different to "=". * represents any number of any character. ? represents a single character. # represents a single digit. [A - S] represents any character between A and S. W[ae*] means starting with W followed by a or e then any other characters. W[!ae]* starting with W and not followed by a or e. *[*]* contains an asterisk. *[?]* contains a question mark.

Introduction to Access SQL (acc-8)

24

Introduction to Access SQL(acc-8)

Testing for unknown values


8.5 List the patients with no town given: (Open the query Example 04d) Field Sort Show Criteria 8.6 Look at the SQL: SELECT Patients.PatientID, Patients.[Family name], Patients.Town FROM Patients WHERE (((Patients.Town) Is Null)); Is Null is used to test for an unknown value. Unknown values are distinguished from 0, so when averages etc are calculated, any blank values are ignored. is null PatientID Family name Town

Create your own queries using SQL only


List drug names, costs and numbers in pack where they cost more than 30p and have more than 40 in a pack. List drug names only whose name comes between A and P or begin with an S. List patients who have a question mark in their name. List patients names who are not on the phone. List patients who live in Bristol, Bath or Nailsea (using the in operator). Give a unique list of family names which do not start with M. Check the queries in the design and datasheet views.

Introduction to Access SQL (acc-8)

25

Introduction to Access SQL(acc-8)

Task 9 Creating a parameter query


Objectives Comments
SQL can be used for prompted queries. A parameter query (or prompted query) is a type of select query which is useful if you frequently run the same query but change the criteria each time you run it. The parameter is specified by using square brackets around the prompt. Once the query is created you can re-run it with different values without opening the query window or making changes in the QBE grid; instead Access prompts you for a value each time. You can specify as many parameters as you want.

Prompted query
9.1 List the patients for a given town: (Open the query Example 08a) Field Table Sort Show Criteria Or like [first few letters of surname]&"*" [Whichtown] Initials Patients Given name Patients Family name Patients Town Patients

The prompt is enclosed in square brackets, for instance "Which town?" (This should not be the name of a field otherwise Access compares it with the value of that field)

9.2

Look at the SQL: SELECT Patients.Initials, Patients.[Given name], Patients.[Family name], Patients.Town FROM Patients WHERE (((Patients.[Family name]) Like [first few letters of surname] & "*") AND ((Patients.Town)=[which town])); Note the parameter names enclosed in square brackets, just like the fieldnames which have spaces as part of the name.

Create your own query using SQL only


Using the Drugs table, find drug names, the cost per packet and the number of tablets per packet, asking each time where there are more than a certain number in the packet.

Introduction to Access SQL (acc-8)

26

Introduction to Access SQL(acc-8)

Task 10 Action queries


Objectives Comments
SQL can be used to change the values of the data. Action queries enable you to make large numbers of similar changes to a database easily. There are three types of action query: Delete deletes records from a table DELETE Drugs.[Drug name] FROM Drugs WHERE (((Drugs.[Drug name])="smarties")); adds a record by specifying values or records from one or more tables Append to another table: The following adds one record using specified values for DrugID and cost. insert into Drugs(DrugID,cost) values ('Polo",.3) The following adds one or more records from existing data in another table: insert into Drugs (DrugID) select distinct DrugID from treatment where not exists (select * from drugs where drugs.DrugID=treatment.DrugID) changes the data in a specified group of records. It advisable to run Update some tests to make sure your update query performs satisfactorily before using it to change a large number of records. It is also advisable to backup your database before running an update query. Update can only be used on one table at a time. update drugs set [cost per packet]= [cost per packet]*1.1 where [tablets per packet]>50 Note that an update query can only be performed on one table at a time - see the query Example 10a

Create your own query using SQL only


In the treatment table, double the dosage of anyone taking Crme eggs (DG1 in drugs table). From the treatment table, delete patients under Dr Sarah Hudson (DoctorID = 10) she gave them an overdose of crme eggs!

Introduction to Access SQL (acc-8)

27

Introduction to Access SQL(acc-8)

Task 11 The iif function


Objectives Comments
To have more practice with functions. Functions can be used to avoid creating new fields in a table, thus making sure that the calculated field is up to date. You can use iif to return more meaningful values than are stored in the database, and to do calculations based on the field value. iif requires the name of the field or an expression, followed by the criteria, and the values to be returned if true and false. In the example below, if gender is m, "male" is returned, otherwise "female" is returned. If you use a mathematical operator to find a value and one of the fields is blank, the result is a null value. To prevent this you can use the iif function to check and produce an error message, for instance, if a date is missing from a field used in a calculation the message might ask you to check for a missing date. Function nz may also be used to give a value if none is supplied for example, nz(gender,"none given").

Using iif
Use iif to expand the values "m" and "f" to "male" and "female" in the output. (Open the query Example 12a). Field Table Sort Show Criteria gendername:iif (Gender="m", "male", "female") Gender Patients PatientID Patients

11.1

Look at the SQL: SELECT IIf([Gender]='m','male','female') AS gendername, Patients.Gender, Patients.PatientID FROM Patients;

Group iif
Find, for each drug, the dosage by each gender. In this example the clause: iif(gender,"m", dosage, null) selects the dosage if gender = "m"; otherwise the value is set to the null value and is not included in the calculation of the average. (Open the query Example12b) Field Table Total Sort Show Criteria
Introduction to Access SQL (acc-8) 28

Drug name Drugs Group by Ascending

maledose: femaledose:Iif([Gender]= Iif([Gender]='m',[dosage],Null) 'f',[dosage],Null) Avg Avg

Introduction to Access SQL(acc-8)

11.2

Look at the SQL: SELECT Drugs.[Drug name], Avg(IIf([Gender]='m',[dosage],Null)) AS maledose, Avg(IIf([Gender]='f',[dosage],Null)) AS femaledose FROM Drugs INNER JOIN (Patients INNER JOIN Treatment ON Patients.PatientID = Treatment.PatientID) ON Drugs.DrugID = Treatment.DrugID GROUP BY Drugs.[Drug name]; This type of query calculates an average on records then groups the result by two different ways - one down the left side (the group by clause) and the other across the top (the aggregated functions). The field aliases Maledose and Femaledose are used to specify the field names.

Introduction to Access SQL (acc-8)

29

Introduction to Access SQL(acc-8)

Task 12 Crosstab Query


Objectives Comments
To see the SQL for a crosstab query. Crosstabs are used to produce summaries of data. The non-standard SQL transform and pivot clause is introduced. An alternative method of summarizing data other than using the group by clause is to create a crosstab query. The default automatically produces headings for each different value it finds rather than specifying them specifically as in Task 5. The following query again displays the average drug use by gender. Use the Crosstab query wizard (the wizard can only be used on a single table or query and we want to incorporate fields from three tables). (Open the query Example13a) Field Table Drugname Example 09b query using multiple tables Group By Row Heading Ascending Gender Example 09b query using multiple tables Group By Column Heading The Value: Dosage Example 09b query using multiple tables Avg Value Row Summary: Dosage Example 09b query using multiple tab Avg Row Heading

Total Crosstab Sort Show

Introduction to Access SQL (acc-8)

30

Introduction to Access SQL(acc-8)

12.1

Look at the SQL:

TRANSFORM Avg([Example 09b query using multiple tables].Dosage) AS [The Value] SELECT [Example 09b query using multiple tables].[Drug name] AS Treatment, Avg([Example 09b query using multiple tables].Dosage) AS [Row Summary] FROM [Example 09b query using multiple tables] GROUP BY [Example 09b query using multiple tables].[Drug name] PIVOT [Example 09b query using multiple tables].Gender; Note the new transform and pivot clauses (non-standard SQL) which precede and follow the select statement: TRANSFORM aggregate function SELECT statement PIVOT pivotfield [IN (value1[, value2[, ...]])] Transform is the field that will have the function performed on it the value as shown in the grid. Transform is optional but when included it is the first statement in an SQL string. It precedes a SELECT clause that specifies the fields used as row headings and a GROUP BY clause that specifies row grouping. Optionally, you can include other clauses, such as WHERE. The values returned in pivotfield are used as field headings in the query's datasheet. For example, pivoting the sex figures would create two fields. You can restrict pivotfield to create headings from fixed values (value1, value2) listed in an optional IN clause. You can also include fixed values for which no data exists to create additional fields. Select specifies the vertical grouping. It is the row heading of the grid. Pivot specifies that for each unique value of that field, a new field will be shown, so one would choose a field with fewer unique values than one chose for the row heading to make display longer rather than wider. It is the colum heading of the grid. Row summary is the field with the function performed on it before being grouped by the field, that is average dose for each drug for each person as opposed to average dose for each drug for each gender.

Introduction to Access SQL (acc-8)

31

Introduction to Access SQL(acc-8)

Task 13 Date handling


Objectives Comments
More exercises with date functions. These exercises give you more practice using date functions. Dates can be displayed in different formats. (See Access query language elements (document acc-r4). The format function specifies the date format using keywords, for example "Dddd". The case of the keyword specifies the case of the output, for example "MMMM" outputs the month name in capital letters. Arithmetic can be performed on dates using the DateDiff function.

Date format
To display the dates in a different format. (Open the query example14a) Field Family Date of name Birth Formatted date: Year of Birth: Format([Date of Birth], format([date of birth], "dddd Mmmm d") "yyyy")

Sort Show 13.1

Look at the SQL: SELECT Patients.[Family name], Patients.[Date of Birth], Format([Date of Birth],"dddd mmmm d ") AS [formatted date], Format([date of birth],"yyyy") AS Year FROM Patients; AS assigns a name to the calculated field.

Date functions
13.2 Examples 14b and 14c show further examples of date functions.

Age calculation
13.3 To find the age of each patient add the Patients table and insert the following fields and options. (Open the query Example 4d) Field Table Sort Show Date of Birth Patients Age:DateDiff("d",[Date of Age_round:int(DateDiff("d",[D Birth],Now())/365.25 ate of Birth],Now()))/365.25) Patients

Introduction to Access SQL (acc-8)

32

Introduction to Access SQL(acc-8)

13.4

Look at the SQL: SELECT Patients.[Family name], Patients.[Date of Birth], DateDiff('d',[Date of Birth],Now())/365.25 AS age, int(DateDiff('d',[Date of Birth],Now())/365.25) AS age_round FROM Patients; The date function DateDiff returns the difference in the given period (for example, "m" for months) between two dates. If two dates are subtracted using the minus (-) operator, the answer is given in days. The int function rounds the age down. Using "yyyy" as the interval does not give the correct age as only the year is considered, not the day and month.

Introduction to Access SQL (acc-8)

33

Introduction to Access SQL(acc-8)

Task 14 Define your own group values


Objectives Comments
To group information into specified ranges without having to run lots of queries. By creating a new range table, the ranges can easily be changed if needed. To find how many patients are in the specified age ranges rather than each unique age, a new table can be created to hold the description and upper and lower bounds of each range of values. 14.1 Construct a new table AGE-RANGE with fields (age_range char(13), age_min integer, age_max integer) to specify the required ranges of age. This is a very flexible way of summarising results because the range can easily be altered by changing the values in the age_range table. age_range 1-10 11-20 21-30 31-40 41-50 51-60 61-70 71-> age_min 1 11 21 31 41 51 61 71 age_max 10 20 30 40 50 60 70 99

14.2

See what happens if you group an explicitly specified age range. (Open the query Example15a) SELECT DateDiff('m',[DATE OF BIRTH],Now())/12, Count(Patients.PatientID) AS CountOfPatientID FROM Patients WHERE DateDiff('m',[DATE OF BIRTH],Now())/12 Between 20 and 30 GROUP BY DateDiff('m',[DATE OF BIRTH],Now())/12;

14.3

Using a query with the age_range table, the patients can then be grouped into each range. You would have to create a separate query for each range unless you did a parameter query but even then you can only look at one range at a time. Field Table Total Sort Show Criteria between age_min and age_max age_range age_range Group By PatientID Patients Count where DateDiff("m",[birth_date],Now())/12

Introduction to Access SQL (acc-8)

34

Introduction to Access SQL(acc-8)

14.4

Look at the SQL: SELECT age_range.age_range, Count(Patients.PatientID) AS CountOfPatientID FROM Patients, age_range WHERE (((DateDiff('m',[DATE OF BIRTH],Now())/12) Between [AGE_MIN] And [AGE_MAX])) GROUP BY age_range.age_range; The field name used in the order by clause must appear in either the select or the group by clause. The join is performed by the between criteria on the age expression, not by an inner join. The age-range field then shows the age range into which the patient falls. It is also easy to modify the age-range table later if the ages need to be regrouped. Age_min and age_max must have the same data type as each other and the same data type as the calculated field (in this case integer).

Introduction to Access SQL (acc-8)

35

Introduction to Access SQL(acc-8)

Task 15 Queries within queries


Objectives Comments
To find a value based on the results of another query using one query only. Queries within queries (nested queries or sub-queries) are queries which use SQL select statements inside another query. The select statement has a select clause to specify the names of the fields, a from clause to specify the name of the tables used and an optional where clause to specify criteria. The select statement must be enclosed in parentheses.

Nested query
Find the drug used which had the biggest dosage and give the dosage. (Open the query Example16a) Field Table Sort Show Criteria 15.1 Look at the SQL: SELECT Drugs.[Drug name], Treatment.Dosage FROM Drugs INNER JOIN Treatment ON Drugs.DrugID = Treatment.DrugID WHERE (((Treatment.Dosage)= (select max([dosage]) from treatment))); In this example, SQL carries out the select clause within the parentheses first (so finds the max dose first). The single value produced as a result of this selection is then used by the where clause of the first select clause. In Task 5 you specifically gave a particular count (>3) as the criterion for when to display the values. In this query you calculate the current maximum dosage and then use this as the criterion for the rest of the query. The inner query must produce a single value (maximum dosage) for the equality criterion of the outer query to work. If it produces more than one value you will get an error message At most one record can be returned. (select max(dosage) from treatment) Drug name Drugs Dosage Treatment

Introduction to Access SQL (acc-8)

36

Introduction to Access SQL(acc-8)

Task 16 Calculating percentages


Objectives Comments
To show how to calculate a percentage using a query. Complex queries can be simplified by using other queries to query them. Having created a query it can then be treated in the same way as a table. A report can also be used to show percentages. Calculating a percentage is done in three stages: 1. Create a query to find the number of doses that have been taken for each drug. 2. Create a query to find the number of doses in total. 3. Find the percentage of the total number using the results of the first two queries. (Open the query Examples 17a - c). 16.1 First create a query as follows called Each_Drug using the Treatment and Drug tables. This is to find the dose for each drug. (Open the query Example17a) Field Table Total Sort Show 16.2 Drug name Drugs Group by Ascending sum Drug_cost:sum(dosage*[cost per packet]*[doses per day])

Look at the SQL: SELECT Drugs.[Drug name], Sum([Dosage]*[cost per packet]*[doses per day]) AS drug_cost FROM Drugs INNER JOIN Treatment ON Drugs.DrugID = Treatment.DrugID GROUP BY Drugs.[Drug name];

16.3

Create a second query as follows called Total_Cost using the Treatment table. This is to find the total dose. (Open the query example17b) Field Table Sort Show Total_cost:sum(dosage*[cost per packet]*[doses per day]) Treatment

Introduction to Access SQL (acc-8)

37

Introduction to Access SQL(acc-8)

16.4

Look at the SQL: SELECT Sum([Dosage]*[cost per packet]*[doses per day]) AS [total cost] FROM Drugs INNER JOIN Treatment ON Drugs.DrugID = Treatment.DrugID; This only returns one row and one column. Then create a query called Percent_Cost to find the percentages using the Each_Drug and Total_Cost queries. (Open the query Example17c). Field Table Sort Show Drug name Drugs Ascending Drug_cost Percent:drug_cost/total_cost

16.5

Look at the SQL: SELECT [Example 16a each drug].[Drug name], [Example 16a each drug].drug_cost, [drug_cost]/[total cost] AS [percent] FROM [Example 16a each drug], [Example 16b total cost]; Percentage found by dividing the cost of each drug by the total cost. This is a good example of showing how queries can be used to simplify queries Another method is to use fields as they are derived in the query. This however is not standard SQL. Example 14c shows the expression for cost: Sum([dosage]*[cost per packet]) and then the expression for percent: [cost]/[total cost] using the value for cost which was derived in the previous field. SELECT Drugs.[Drug name], Sum([dosage]*[cost per packet]) AS cost, [cost]/[total cost] AS [percent] FROM [Example 14b total cost], Drugs INNER JOIN Treatment ON Drugs.DrugID = Treatment.DrugID GROUP BY Drugs.[Drug name], [Example 14b total cost].[total cost];

Introduction to Access SQL (acc-8)

38

Introduction to Access SQL(acc-8)

Task 17 Unmatched query


Objectives Comments
Find data that is in one table but not in another. This is very useful when trying to achieve referential integrity (for example, all patients are taking drugs for which information is known), so you need to identify treatment drugs for which there is no information about the drug given, and patients given treatment who are unknown. There are three kinds of join between tables: 1. The default is for the query to only include records from both tables that share a common value for a field. Thus a query on the DRUG and TREATMENT table will only list those drugs that have been used in treatments. This is the equi-join or inner join. 2. The second way is to include records from the primary table regardless of whether or not a record matches a record in the other table. Thus, drugs can be listed regardless of whether they have been used in treatments or not. This is the left outer join. 3. The third way is to include records from the other table regardless of whether or not a record matches a record in the primary table. This is a right outer join. Thus, the query can display all treatment records regardless of whether they have details in the drug table. This would break referential integrity since it should not be possible to prescribe a drug if it was unknown. Thus unmatched queries can also be useful when one is trying to set up referential integrity between two tables. 17.1 Find the drugs not used in treatment using the unmatched query wizard. (Open the query Example18a) Field Table Sort Show Criteria Look at the SQL: DrugID Drugs Ascending is null Drugname Drugs DrugID Treatment

SELECT Drugs.DrugID, Drugs.[Drug name] FROM Drugs LEFT JOIN Treatment ON Drugs.DrugID = Treatment.DrugID WHERE (((Treatment.DrugID) Is Null));

This is the SQL created using the Unmatched query wizard using the outer join method. Look at the join line between the two tables. It should have an arrow on it. Click on the join line to check the properties of the join.

Introduction to Access SQL (acc-8)

39

Introduction to Access SQL(acc-8)

The second DrugID field is from the Treatment table and is tested for not null since there are no treatments for that drug. Note LEFT JOIN indicates that drugs will be listed regardless of whether they appear in the treatment table. The first named table is the primary table. RIGHT JOIN would indicate treatment using unknown drugs (would then have to check Drug - DrugID is null). The first named table is still the primary table. There are other ways of doing this query: exists operator (more efficient and standard SQL) not in operator (less efficient but standard SQL).

not exists operator


(Open the query Example18b) SELECT Drugs.DrugID, Drugs.[Drug name] FROM Drugs WHERE not exists(select * from Treatment where Drugs.DrugID = Treatment.DrugID); This is the more conventional SQL solution If you put not exists in the criterion grid you will get a type mismatch error unless you put the criterion on the join field DrugID since it unexpectedly generates: WHERE ((Not (Drugs.DrugID) =Exists (select * from Treatment where Drugs.DrugID = Treatment.DrugID)));

The not in operator can also be used as can be seen in the next example (far more efficient than the not exists operator since it uses indexes.

not in method
(Open the query Example18c) SELECT Drugs.DrugID, Drugs.[Drug name] FROM Drugs WHERE DrugID not in (select DrugID from Treatment ); The not in method is very inefficient as no indexes are used so can be very slow if there is a lot of data.

Introduction to Access SQL (acc-8)

40

Introduction to Access SQL(acc-8)

Task 18 Creating tables


Objectives Comments
To create a table using SQL rather than the Table button. Microsoft Access tables are normally built using the Table button, but it is also possible to create a table using an SQL query. This is only normally used if you want to send SQL to a non-Access database. You must select 'data definition' from the 'Query type' menu when creating your table. Note that the datatypes are given as: text, datetime, byte, short, integer, single, double, binary, boolean, currency. Text needs an argument to specify the maximum number of characters that can be entered. 18.1 The SQL command create table creates a table. For example, to create the example database tables. (Open the query Example 19a) create table Drugs( DrugID text(6) constraint drugtablekey primary key, Drugname text(40) not null, Tablets_per_packet integer, Cost_per_packet currency; The maximum length of Access table and field names is 64 characters. You are recommended for efficiency to use fewer than 10 characters. The maximum number of fields in an Access table is 255. The names of tables are given in capitals by convention; in fact, case is ignored except in text strings. Note that spaces may not be used in field names when creating tables in this way. Access does not distinguish between names typed in different cases and is very bad at checking for reserved words. Name is not an Access reserved word but can cause problems if a field has that name. Look at the Access help file for reserved words. not null specifies that every entry in the table must have a value for that field. In Drugs, each 'Drug' is defined to be unique and thus is designated as the primary key (fields used to uniquely identify a table). More than one field may form the primary key. Note the primary key option.

Introduction to Access SQL (acc-8)

41

Introduction to Access SQL(acc-8)

Task 19 Table Constraints


Objectives Comments
Specify the primary key and referential integrity of a table using SQL. If you want to add constraints later using SQL you can alter the table definition using Data definition from the Query type menu. This is only normally used if you want to send SQL to a non-Access database.

19.1

Look at the SQL: alter table DRUGSSQL add constraint DRUGS_pk primary key (DrugID) ; This creates a primary key for the table alter table TREATMENT add constraint TREATMENT_fk foreign key(DrugID) references DRUGS(DrugID). The 'references' clause shows the relationship between the DRUGS and TREATMENT tables. DRUGS and TREATMENT are related by the field DrugId. DrugId in TREATMENT is the foreign key (one or more fields whose values are based on the primary key from another table and used to specify the relationship between two tables). Note that referential constraints are normally added by editing the relationships diagram in Access, and field validity is added by editing the properties of the table. Any query, form or report built can incorporate these constraints automatically, provided they were defined before the query, form or report was built. The foreign key ensures that records added to the treatment table will relate to a known Drug. If you add a foreign key, it must be the same as the primary key of the related table and the primary key clause must have been used on that table definition. Value constraint (which for example ensures that the field can contain only values between 1 and 4) cannot be used in Access SQL.

Introduction to Access SQL (acc-8)

42

Introduction to Access SQL(acc-8)

Task 20 Create an index


Objectives Comments
Create an index using SQL. If you want to add indices later using SQL you can use Data definition from the Query type menu. This is particularly useful if using ODBC and the attached table has no unique index (which also means you can not add data). This is only normally used if you want to send SQL to a non-Access database. Tables can have any number of indices. There are two reasons for creating an index: 1. Creating an index based on fields which are to be used in relating one table to another, 2. Or a field which is queried frequently makes accessing the table faster. 20.1 A unique index ensures that the rows can be uniquely identified using the fields specified (you would normally use the 'primary key' clause as in Task 20). A table must have a primary key if it is to have other tables linked to it. Look at the SQL: create unique index TREATMENT_IND on TREATMENT (DrugID); This creates a unique index on the DrugId field of the treatment table.

20.2

Introduction to Access SQL (acc-8)

43

Introduction to Access SQL(acc-8)

Appendix A

SQL syntax
SELECT [predicate] { * | table.* | [table.]field1 [, [table.]field2.[, ...]]} [AS alias1 [, alias2 [, ...]]] FROM table or query [, ...] [IN externaldatabase] [WHERE... ] [GROUP BY... ] [HAVING... ] [ORDER BY... ]

Standard SQL select statement

where predicate is all, any, distinct This shows the basic order of the SQL clauses.

Access SQL syntax


[TRANSFORM]aggfn(cell value) SELECT [predicate] { * | table.* | [table.]field1 [, [table.]field2.[, ...]]} [AS alias1 [, alias2 [, ...]]] FROM tableexpression [, ...] [IN externaldatabase] [INNER JOIN table 2 on table1=table2.field1 and table2 on table1.field2=tabl2.field2...] [RIGHT JOIN table 2 on table1=table2.field1 and table2 on table1.field2=tabl2.field2...] [LEFT JOIN table 2 on table1=table2.field1 and table2 on table1.field2=tabl2.field2...] [WHERE... ] [GROUP BY... ] [HAVING... ] [ORDER BY... ] [PIVOT fieldheading] [WITH OWNERACCESS OPTION] predicate are all, distinct, distinctrow, top, percent (for example, select top 10 gives the first 10 records) WITH OWNERACCESS OPTION gives the user in a multi-user environment ,permission to view the data in a query even if the user is otherwise restricted from viewing the query's underlying tables.

A four table join:


SELECT ..... FROM Doctors INNER JOIN (Drugs INNER JOIN (Patients INNER JOIN Treatment ON Patients.PatientID = Treatment.PatientID) ON Drugs.DrugID = Treatment.DrugID) ON Doctors.DoctorID = Treatment.DoctorID;

Introduction to Access SQL (acc-8)

A-1

Introduction to Access SQL(acc-8)

Delete statement
PURPOSE: SYNTAX: DELETE [FROM] table [WHERE condition] WHERE deletes only rows that satisfy the condition. The condition can reference the table and can contain a subquery. If you omit this clause, Oracle deletes all rows from the table. Rows can only be deleted from one table at a time. To remove rows from a table. Use Delete action query to see this SQL.

INSERT command
PURPOSE: SQL. SYNTAX: INSERT INTO table [ (column [, column] ...) ] {VALUES (expr [, expr] ...) | subquery} To add rows to a single table. Use Append action query to get this

UPDATE command
PURPOSE: To change existing values in a single table. Use Update action query to get this SQL. SYNTAX: UPDATE table SET { (column [, column] ...) = (subquery) | column = { expr | (subquery) } } [, { (column [, column] ...) = (subquery) | column = { expr | (subquery) } } ] ... [WHERE condition]

Introduction to Access SQL (acc-8)

A-2

Introduction to Access SQL(acc-8)

Appendix B

Data dictionary

The data dictionary is used to find out what tables and so on have been created. The data dictionary is populated automatically and cannot be updated by the user. Access does not provide a proper data dictionary. If Access Options is selected from the Office button(choose Current database, then Navigation options and Show system objects) and system objects is set to yes, then several extra tables are listed whose names start with MSys, for example MSysObjects, and these can be examined. Database Tools/Database Documenter is also very useful.

Introduction to Access SQL (acc-8)

B-1

You might also like