Build the query in Design view

  1. Open the Northwind database. Close the login form.
  2. On the Create tab, in the Queries group, click Query Design.
    The Show Table dialog box opens.
  3. In the Show Table dialog box, double-click Customers, Orders, and Order Details, and then click Close.
    All three tables appear in the query design workspace.
  4. In the Customers table, double-click the City field to add it to the query design grid.
  5. In the query design grid, in the City column, in the Criteria row, type In ('Rio de Janeiro','São Paulo'). This causes only those records where the customer is in one of these two cities to be included in the query.
  6. In the Order Details table, double-click the ShippedDate and the UnitPrice fields.
    The fields are added to the query design grid.
  7. In the ShippedDate column in the query design grid, select the Field row. Replace [ShippedDate] with Year: Format([ShippedDate],'yyyy'). This creates a field alias, Year, that allows you to use just the year portion of the value in the ShippedDate field.
  8. In the UnitPrice column in the query design grid, select the Field row. Replace [UnitPrice] with Sales: [Order Details].[UnitPrice]*[Quantity]-[Order Details].[UnitPrice]*[Quantity]*[Discount]. This creates a field alias, Sales, that calculates the sales for each record.
  9. On the Design tab, in the Query Type group, click Crosstab.
    Two new rows, Total and Crosstab, appear in the query design grid.
  10. In the City column in the query design grid, click the Crosstab row, and then click Row Heading.
    This makes city values appear as the row headings (that is, the query returns one row for each city).
  11. In the Year column, click the Crosstab row, and then click Column Heading.
    This makes year values appear as the column headings (that is, the query returns one column for each year).
  12. In the Sales column, click the Crosstab row, and then click Value.
    This makes sales values appear at the intersection of rows and column (that is, the query returns one sales value for each combination of city and year).
  13. In the Sales column, click the Totals row, and then click Sum.
    This causes the query to sum the values in this column.
    You can leave the Totals row for the other two columns at the default value of Group By, because you want to see each value for these columns, not aggregate values.
  14. On the Design tab, in the Results group, click Run.

You now have a query that returns the total sales by year in Rio de Janeiro and São Paulo.

View all the records from two similar tables

Sometimes, you will want to combine data from two tables that are identical in structure, but one of them is located in another database. Consider the following scenario.

Suppose you are an analyst working with student data. You are embarking on a data sharing initiative between your school and another school, so that both schools can improve their curricula. For some of the questions you want to explore, it would be better to look at all records from both schools together, rather than each school's records separately.

You could import the other school's data into new tables in your database, but then any changes to the other school's data would not be reflected in your database. A better solution would be to link to the other school's tables, and then create queries that combined the data when you run them. You would be able to analyze the data as a single set, rather than performing two analyses and trying to interpret them as if they were one.

To view all the records from two tables with identical structure, you use a union query.

Union queries cannot be displayed in Design view. You build them by using SQL commands that you enter in a SQL view object tab.

Create a union query by using two tables

  1. On the Create tab, in the Queries group, click Query Design.
    A new query design grid opens, and the Show Table dialog box appears.
  2. In the Show Table dialog box, click Close.
  3. On the Design tab, in the Query Type group, click Union.
    The query switches from Design view to SQL view. At this point, the SQL view object tab is empty.
  4. In SQL view, type SELECT, followed by a list of the fields from the first of the tables you want in the query. Field names should be enclosed in square brackets, and separated by commas. When you have finished typing the field names, press ENTER. The cursor moves down one line in SQL view.
  5. Type FROM, followed by the name of the first of the tables you want in the query. Press ENTER.
  6. If you want to specify a criterion for a field from the first table, type WHERE, followed by the field name, a comparison operator (usually, an equals sign (=)), and the criterion. You can add additional criteria to the end of the WHERE clause by using the AND keyword and the same syntax used for the first criterion; for example, WHERE [ClassLevel]='100' AND [CreditHours]>2. When you are finished specifying criteria, press ENTER.
  7. Type UNION, and then press ENTER.
  8. Type SELECT, followed by a list of the fields from the second table you want in the query. You should include the same fields from this table that you included from the first table, and in the same order. Field names should be enclosed in square brackets, and separated by commas. When you have finished typing the field names, press ENTER.
  9. Type FROM, followed by the name of the second table you want to include in the query. Press ENTER.
  10. If you want, add a WHERE clause, as described in step 6 of this procedure.
  11. Type a semicolon (;) to indicate the end of your query.
  12. On the Design tab, in the Results group, click Run.
    Your results appear in Datasheet view.

See Also

Home > Articles
  1. Retrieving Records from Multiple Tables
< BackPage 5 of 11Next >
This chapter is from the book
MySQL, 2nd Edition

This chapter is from the book

This chapter is from the book

Retrieving Records from Multiple Tables

It does no good to put records in a database unless you retrieve them eventually and do something with them. That's the purpose of the SELECT statement—to help you get at your data. SELECT probably is used more often than any other in the SQL language, but it can also be the trickiest; the constraints you use to choose rows can be arbitrarily complex and can involve comparisons between columns in many tables.
The basic syntax of the SELECT statement looks like this:
Everything in this syntax is optional except the word SELECT and the selection_list part that specifies what you want to retrieve. Some databases require the FROM clause as well. MySQL does not, which allows you to evaluate expressions without referring to any tables:
In Chapter 1, we devoted quite a bit of attention to single-table SELECT statements, concentrating primarily on the output column list and the WHERE, GROUP BY, ORDER BY, HAVING, and LIMIT clauses. This section covers an aspect of SELECT that is often confusing—writing joins; that is, SELECT statements that retrieve records from multiple tables. We'll discuss the types of join MySQL supports, what they mean, and how to specify them. This should help you employ MySQL more effectively because, in many cases, the real problem of figuring out how to write a query is determining the proper way to join tables together.
One problem with using SELECT is that when you first encounter a new type of problem, it's not always easy to see how to write a SELECT query to solve it. However, after you figure it out, you can use that experience when you run across similar problems in the future. SELECT is probably the statement for which past experience plays the largest role in being able to use it effectively, simply because of the sheer variety of problems to which it applies.
As you gain experience, you'll be able to adapt joins more easily to new problems, and you'll find yourself thinking things like, 'Oh, yes, that's one of those LEFT JOIN things,' or, 'Aha, that's a three-way join restricted by the common pairs of key columns.' (I'm a little reluctant to point that out, actually. You may find it encouraging to hear that experience helps you. On the other hand, you may find it alarming to consider that you could wind up thinking in terms like that!)
Look out for the sparkly guitar, cat, fruits and more in each room. Match her outfits and discover something magical! Dora la casa de dora.
Many of the examples that demonstrate how to use the forms of join operations that MySQL supports use the following two tables, t1 and t2. They're small, which makes them simple enough that the effect of each type of join can be seen readily:

The Trivial Join

The simplest join is the trivial join, in which only one table is named. In this case, rows are selected from the named table:
Some people don't consider this form of SELECT a join at all and use the term only for SELECT statements that retrieve records from two or more tables. I suppose it's a matter of perspective.

The Full Join

If a SELECT statement names multiple tables in the FROM clause with the names separated by commas, MySQL performs a full join. For example, if you join t1 and t2 as follows, each row in t1 is combined with each row in t2:
A full join is also called a cross join because each row of each table is crossed with each row in every other table to produce all possible combinations. This is also known as the cartesian product. Joining tables this way has the potential to produce a very large number of rows because the possible row count is the product of the number of rows in each table. A full join between three tables that contain 100, 200, and 300 rows, respectively, could return 100x200x300 = 6 million rows. That's a lot of rows, even though the individual tables are small. In cases like this, a WHERE clause will normally be used to reduce the result set to a more manageable size.
If you add a WHERE clause causing tables to be matched on the values of certain columns, the join becomes what is known as an equi-join because you're selecting only rows with equal values in the specified columns:
The JOIN and CROSS JOIN join types are equivalent to the ',' (comma) join operator. For example, the following statements are all the same:
Normally, the MySQL optimizer considers itself free to determine the order in which to scan tables to retrieve rows most quickly. On occasion, the optimizer will make a non-optimal choice. If you find this happening, you can override the optimizer's choice using the STRAIGHT_JOIN keyword. A join performed with STRAIGHT_JOIN is like a cross join but forces the tables to be joined in the order named in the FROM clause.
STRAIGHT_JOIN can be specified at two points in a SELECT statement. You can specify it between the SELECT keyword and the selection list to have a global effect on all cross joins in the statement, or you can specify it in the FROM clause. The following two statements are equivalent:
Qualifying Column References
References to table columns throughout a SELECT statement must resolve unambiguously to a single table named in the FROM clause. If only one table is named, there is no ambiguity because all columns must be columns of that table. If multiple tables are named, any column name that appears in only one table is similarly unambiguous. However, if a column name appears in multiple tables, references to the column must be qualified by the table name using tbl_name.col_name syntax to specify which table you mean. Suppose a table mytbl1 contains columns a and b, and a table mytbl2 contains columns b and c. In this case, references to columns a or c are unambiguous, but references to b must be qualified as either mytbl1.b or mytbl2.b:
SELECT a, mytbl1.b, mytbl2.b, c FROM mytbl1, mytbl2 .. ;
Sometimes a table name qualifier is not sufficient to resolve a column reference. For example, if you're joining a table to itself, you're using it multiple times within the query and it doesn't help to qualify a column name with the table name. In this case, table aliases are useful for communicating your intent. You can assign an alias to any instance of the table and refer to columns from that instance as alias_name.col_name. The following query joins a table to itself, but assigns an alias to one instance of the table to allow column references to be specified unambiguously:
SELECT mytbl.col1, m.col2 FROM mytbl, mytbl AS m WHERE mytbl.col1 > m.col1;

Left and Right Joins

An equi-join shows only rows where a match can be found in both tables. Left and right joins show matches, too, but also show rows in one table that have no match in the other table. The examples in this section use LEFT JOIN, which identifies rows in the left table that are not matched by the right table. RIGHT JOIN is the same except that the roles of the tables are reversed. (RIGHT JOIN is available only as of MySQL 3.23.25.)
A LEFT JOIN works like this: You specify the columns to be used for matching rows in the two tables. When a row from the left table matches a row from the right table, the contents of the rows are selected as an output row. When a row in the left table has no match, it is still selected for output, but joined with a 'fake' row from the right table in which all the columns have been set to NULL. In other words, a LEFT JOIN forces the result set to contain a row for every row in the left table whether or not there is a match for it in the right table. The rows with no match can be identified by the fact that all columns from the right table are NULL.
Consider once again our two tables, t1 and t2:
If we use a cross join to match these tables on t1.i1 and t2.i2, we'll get output only for the values 2 and 3, which appear in both tables:
A left join produces output for every row in t1, whether or not t2 matches it. To write a left join, name the tables with LEFT JOIN in between (rather than a comma) and specify the matching condition using an ON clause (rather than a WHERE clause):
Now there is an output row even for the value 1, which has no match in t2.
LEFT JOIN is especially useful when you want to find only those left table rows that are unmatched by the right table. Do this by adding a WHERE clause that looks for rows in the right table that have NULL values—in other words, the rows in one table that are missing from the other:
Normally, what you're really after are the unmatched values in the left table. The NULL columns from the right table are of no interest for display purposes, so you wouldn't bother naming them in the output column list:
LEFT JOIN actually allows the matching conditions to be specified two ways. ON is one of these; it can be used whether or not the columns you're joining on have the same name:
The other syntax involves a USING() clause; this is similar in concept to ON, but the name of the joined column or columns must be the same in each table. For example, the following query joins mytbl1.b to mytbl2.b:
LEFT JOIN has a few synonyms and variants. LEFT OUTER JOIN is a synonym for LEFT JOIN. There is also an ODBC-style notation for LEFT JOIN that MySQL accepts (the OJ means 'outer join'):
NATURAL LEFT JOIN is similar to LEFT JOIN; it performs a LEFT JOIN, matching all columns that have the same name in the left and right tables.
One thing to watch out for with LEFT JOIN is that if the columns that you're joining on are not declared as NOT NULL, you may get problematic rows in the result. For example, if the right table contains columns with NULL values, you won't be able to distinguish those NULL values from NULL values that identify unmatched rows.
As already mentioned, LEFT JOIN is useful for answering 'Which values are missing?' questions. When you want to know which values in one table are not present in another table, you use a LEFT JOIN on the two tables and look for rows in which NULL is selected from the second table. Let's consider a more complex example of this type of problem than the one shown earlier using t1 and t2.
For the grade-keeping project first mentioned in Chapter 1, we have a student table listing students, an event table listing the grade events that have occurred, and a score table listing scores for each student for each grade event. However, if a student was ill on the day of some quiz or test, the score table wouldn't have any score for the student for that event, so a makeup quiz or test should be given. How do we find these missing records so that we can make sure those students take the makeup?
The problem is to determine which students have no score for a given grade event and to do this for each grade event. Another way to say this is that we want to find out which combinations of student and event are not represented in the score table. This 'which values are not present' wording is a tip-off that we want a LEFT JOIN. The join isn't as simple as in the previous example, though, because we aren't just looking for values that are not present in a single column; we're looking for a two-column combination. The combinations we want are all the student/event combinations, which are produced by crossing the student table with the event table:
Then we take the result of that join and perform a LEFT JOIN with the score table to find the matches:
Note that the ON clause allows the rows in the score table to be joined according to matches in different tables. That's the key for solving this problem. The LEFT JOIN forces a row to be generated for each row produced by the cross join of the student and event tables, even when there is no corresponding score table record. The result set rows for these missing score records can be identified by the fact that the columns from the score table will all be NULL. We can select these records in the WHERE clause. Any column from the score table will do, but because we're looking for missing scores, it's probably conceptually clearest to test the score column:
We can put the results in order using an ORDER BY clause. The two most logical orderings are by event per student or by student per event. I'll choose the first:
Now all we need to do is name the columns we want to see in the output, and we're done. Here is the final query:
Running the query produces these results:
Here's a subtle point. The output displays the student IDs and the event IDs. The student_id column appears in both the student and score tables, so at first you might think that the selection list could name either student. student_id or score.student_id. That's not the case because the entire basis for being able to find the records we're interested in is that all the score table fields are returned as NULL. Selecting score.student_id would produce only a column of NULL values in the output. The same principle applies to deciding which event_id column to display. It appears in both the event and score tables, but the query selects event.event_id because the score.event_id values will always be NULL.

Using Subselects

One of the features that MySQL 4.1 introduces is subselect support, which is a long-awaited capability that allows one SELECT query to be nested inside other. The following is an example that looks up the IDs for event records corresponding to tests ('T') and uses them to select scores for those tests:
In some cases, subselects can be rewritten as joins. I'll show how to do that later in this section. You may find subselect rewriting techniques useful if your version of MySQL precedes 4.1.
A related feature that MySQL supports is the ability to delete or update records in one table based on the contents of another. For example, you might want to remove records in one table that aren't matched by any record in another, or copy values from columns in one table to columns in another. These types of operations are discussed in the 'Multiple-Table Deletes and Updates' section later in this chapter.
There are several forms you can use to write subselects; this section surveys just a few of them.

Rewriting Subselects as Joins

For versions of MySQL prior to 4.1, subselects are not available. However, it's often possible to rephrase a query that uses a subselect in terms of a join. In fact, even if you have MySQL 4.1 or later, it's not a bad idea to examine queries that you might be inclined to write in terms of subselects; a join is sometimes more efficient than a subselect.
Rewriting Subselects That Select Matching Values
The following is an example query containing a subselect; it selects scores from the score table for all tests (that is, it ignores quiz scores):
The same query can be written without a subselect by converting it to a simple join:
As another example, the following query selects scores for female students:
This can be converted to a join as follows:
There is a pattern here. The subselect queries follow this form:
Such queries can be converted to a join using the following form:
Rewriting Subselects That Select Non-Matching (Missing) Values
Another common type of subselect query searches for values in one table that are not present in another table. As we've seen before, the 'which values are not present' type of problem is a clue that a LEFT JOIN may be helpful. The following is a query with a subselect that tests for students who are not listed in the absence table (it finds those students with perfect attendance):
This query can be rewritten using a LEFT JOIN as follows:
In general terms, the subselect query form is as follows:
A query having that form can be rewritten like this:
This assumes that table2.column2 is declared as NOT NULL.

Retrieving from Multiple Tables with UNION

If you want to create a result set by selecting records from multiple tables one after the other, you can do that using a UNION statement. UNION is available as of MySQL 4, although prior to that you can use a couple of workarounds (shown later).
For the following examples, assume you have three tables, t1, t2, and t3 that look like this:
Tables t1 and t2 have integer and character columns, and t3 has date and integer columns. To write a UNION statement that combines multiple retrievals, just write several SELECT statements and put the keyword UNION between them. For example, to select the integer column from each table, do this:
UNION has the following properties:
Prior to MySQL 4, UNION is unavailable, but you can work around this difficulty by selecting rows from each table into a temporary table and then selecting the contents of that table. In MySQL 3.23 and later, you can handle this problem easily by allowing the server to create the holding table for you. Also, you can make the table a temporary table so that it will be dropped automatically when your session with the server terminates. For quicker performance, use a HEAP (in-memory) table.
Because tmp is a TEMPORARY table, the server will drop it automatically when your client session ends. (Of course, you can drop the table explicitly as soon as you're done with it to allow the server to free resources associated with it. This is a good idea if you will continue to perform further queries, particularly for HEAP tables.)
For versions of MySQL older than 3.23, the concept is similar, but the details differ because the HEAP table type and TEMPORARY tables are unavailable, as is CREATE TABLE .. SELECT. To adapt the preceding procedure, it's necessary to explicitly create the table first before retrieving any rows into it. (The only table type available will be ISAM, so you cannot use a TYPE option.) Then retrieve the records into the table. When you're done with it, you must use DROP TABLE explicitly because the server will not drop it automatically.
If you want to run a UNION-type query on MyISAM tables that have identical structure, you may be able to set up a MERGE table and query that as a workaround for lack of UNION. (In fact, this can be useful even if you do have UNION, because a query on a MERGE table will be simpler than the corresponding UNION query.) A query on the MERGE table is similar to a UNION that selects corresponding columns from the individual tables that make up the MERGE table. That is, SELECT on a MERGE table is like UNION ALL (duplicates are not removed), and SELECT DISTINCT is like UNION (duplicates are removed).

You might also like:


MySQL, 5th Edition
By Paul Dubois
PHP and MySQL Phrasebook
By Christian Wenz
Sams Teach Yourself PHP, MySQL and Apache All in One, 5th Edition
By Julie Meloni

Related Resources

I am trying to compare two tables, SQL Server, to verify some data. I want to return all the rows from both tables where data is either in one or the other. In essence, I want to show all the discrepancies. I need to check three pieces of data in doing so, FirstName, LastName and Product.
I'm fairly new to SQL and it seems like a lot of the solutions I'm finding are over complicating things. I don't have to worry about NULLs.
I started by trying something like this:
I'm having trouble taking this further though.
Thanks!
EDIT:
Based on the answer by @treaschf I have been trying to use a variation of the following query:
But I keep getting 0 results back, when I know that there is at least 1 row in td that is not in d.
EDIT:
Ok, I think I figured it out. At least in my few minutes of testing it seems to work good enough.
This is basically going to tell me what is in my test data that is not in my real data. Which is completely fine for what I need to do.
Roman Pekar
74.8k23 gold badges141 silver badges159 bronze badges
CaseyCasey
7,13315 gold badges59 silver badges103 bronze badges

10 Answers

IF you have tables A and B, both with colum C, here are the records, which are present in table A but not in B:
To get all the differences with a single query, a full join must be used, like this:
What you need to know in this case is, that when a record can be found in A, but not in B, than the columns which come from B will be NULL, and similarly for those, which are present in B and not in A, the columns from A will be null.
treaschftreaschf
4,4171 gold badge20 silver badges22 bronze badges
Jeffrey Kemp
49.6k12 gold badges93 silver badges136 bronze badges
erikkallenerikkallen
26.3k12 gold badges71 silver badges109 bronze badges
I know that this may not be a popular answer but I do agree with @Randy Minder on using third party tool when more complex comparison is needed.
This specific case here is easy and for this case such tools are not needed but this can get complex easily if you introduce more columns, databases on two servers, more complex comparison criteria and such.
There are a lot of these tools such as ApexSQL Data Diff or Quest Toad and you can always use them in trial mode to get the job done.
Maisie JohnMaisie John
To get all the differences between two tables, you can use like me this SQL request :
bilelovitchbilelovitch
If you want to get which column values are different, you could use Entity-Attribute-Value model:
Roman PekarRoman Pekar
74.8k23 gold badges141 silver badges159 bronze badges
Simple variation on @erikkallen answer that shows which table the row is present in:
Tables
If you get an error
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
then it may help to add
knut
22.8k4 gold badges69 silver badges101 bronze badges
studgeekstudgeek
9,9974 gold badges66 silver badges81 bronze badges
Kango_VKango_V
1,7312 gold badges14 silver badges11 bronze badges
This will do the trick, similar with Tiago's solution, return 'source' table as well.
Combat is more enjoyable, although often more difficult. Divinity original sin 2 replayability.
result will contain differences between tables, in column _tabloc you will have table reference.
Community

Sql Access Show Items Where Not Be On Two Tables In One

Adrian-Bogdan IonescuAdrian-Bogdan Ionescu
For a simple smoke test where you you're trying to ensure two tables match w/out worrying about column names:
You can easily write a store procedure to compare a batch of tables.
thomas398thomas398

Select From Multiple Tables Sql

There is a performance issue related with the left join as well as full join with large data.
In my opinion this is the best solution:
Tiago MoutinhoTiago Moutinho
9311 gold badge11 silver badges18 bronze badges

Sql Access Show Items Where Not Be On Two Tables Near Me

protected by CommunityOct 16 '15 at 0:17

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged sqlsql-serversql-server-2008sql-server-2005 or ask your own question.