Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Since this is a homework assignment, I would like to provide some input on how to design the tables in a proper manner. Just my two cents.</p> <h3>Design suggestion</h3> <p>I would suggest that you alter the table design. All your tables essentially contain the same data:</p> <ul> <li>a number</li> <li>name</li> </ul> <p>Instead of having multiple tables, you should design your database something along this line that would include only two tables.</p> <pre><code>Department ---------- dept_no INTEGER dept_name VARCHAR(30) Person ------ person_no INTEGER person_name VARCHAR(30) dept_no INTEGER </code></pre> <h3>Create tables with constraints</h3> <p>You should design tables with appropriate constraints. Here are few things to note.</p> <ul> <li><p>The constraint <code>PRIMARY KEY</code>, as the name states, would create a primary key on the table to keep the data unique so that you don't end up with multiple ids with the same value.</p></li> <li><p>The constraint <code>FOREIGN KEY</code> is creating a relation between the tables Department and Person.</p></li> <li><p>For this example, these keys may not be necessary but in real world applications it is always a best practice to define proper relations using the foreign key constraints. There are lots of other things you can search about <code>PRIMARY KEY</code> and <code>FOREIGN KEY</code> on the web.</p></li> <li><p>You cannot switch the order in which these tables are created. In other words, you cannot create Person table first and then the Department table. The reason is that Person table is creating a constraint that references the Department table. If you create the Person table first, you will get the error <code>Failed: ORA-00942: table or view does not exist</code>.</p></li> <li><p>You can also make the <code>dept_no</code> and <code>person_no</code> to be auto incremented numbers so that you don't have to manually insert those numbers. I use SQL Server. So, I am not much familiar with Oracle syntax to make a column to auto incremented number. Search for sequence number for Oracle, you might find something.</p></li> </ul> <p><em>Script</em>:</p> <pre><code>CREATE TABLE Department ( dept_no INTEGER , dept_name VARCHAR(30) , CONSTRAINT pk_department PRIMARY KEY (dept_no) ); CREATE TABLE Person ( person_no INTEGER , person_name VARCHAR(30) , dept_no INTEGER , CONSTRAINT pk_person PRIMARY KEY (person_no) , CONSTRAINT fk_person_dept FOREIGN KEY (dept_no) REFERENCES Department (dept_no) ); </code></pre> <h3>Populate the table</h3> <ul> <li><p>Below given script first populates the Department table and then populates the Person table.</p></li> <li><p>It is actually inserting multiple values into the table at the same time instead of calling INSERT INTO for every single row. </p></li> <li><p><strong><em>dual</em></strong> is a dummy table in Oracle with single row. <a href="https://stackoverflow.com/questions/73751/what-is-the-dual-table-in-oracle"><strong>Read here in this SO answer about dual.</strong></a></p></li> </ul> <p><em>Script</em>:</p> <pre><code>INSERT ALL INTO Department (dept_no, dept_name) VALUES (1, 'Cleaner') INTO Department (dept_no, dept_name) VALUES (2, 'Driver') INTO Department (dept_no, dept_name) VALUES (3, 'Mechanic') SELECT * FROM dual; INSERT ALL INTO Person (person_no, person_name, dept_no) VALUES (1, 'Cleaner 1', 1) INTO Person (person_no, person_name, dept_no) VALUES (2, 'Cleaner 2', 1) INTO Person (person_no, person_name, dept_no) VALUES (3, 'Cleaner 3', 1) INTO Person (person_no, person_name, dept_no) VALUES (4, 'Cleaner 4', 1) INTO Person (person_no, person_name, dept_no) VALUES (5, 'Driver 1', 2) INTO Person (person_no, person_name, dept_no) VALUES (6, 'Driver 2', 2) INTO Person (person_no, person_name, dept_no) VALUES (7, 'Driver 3', 2) INTO Person (person_no, person_name, dept_no) VALUES (8, 'Mechanic 1', 3) INTO Person (person_no, person_name, dept_no) VALUES (9, 'Mechanic 2', 3) INTO Person (person_no, person_name, dept_no) VALUES (10, 'Mechanic 3', 3) INTO Person (person_no, person_name, dept_no) VALUES (11, 'Mechanic 4', 3) INTO Person (person_no, person_name, dept_no) VALUES (12, 'Mechanic 5', 3) INTO Person (person_no, person_name, dept_no) VALUES (13, 'Mechanic 6', 3) SELECT * FROM dual; </code></pre> <h3>How to get my data grouped by department?</h3> <ul> <li><p>Now that you have the table and data, it is time to query the information.</p></li> <li><p>Your requirement is to get the list of all the departments and the number of people in each department.</p></li> <li><p>If you run the following query, you will simply get the list of departments but that is not what you need.</p></li> </ul> <p><em>Simple Select</em>:</p> <pre><code>SELECT dept_no , dept_name FROM Department; </code></pre> <p><em>Output</em>:</p> <pre><code>DEPT_NO DEPT_NAME ------- --------- 1 Cleaner 2 Driver 3 Mechanic </code></pre> <ul> <li>So, you might ask '<em>How can I get that information?</em>'. Well, that information is in the table Person. So, we need to join both the tables to find the desired data. We will use <code>INNER JOIN</code> to join both the tables on a common field. In this case, the common field in both the tables is <strong>dept_no</strong>. </li> </ul> <h3>Query that will give you the desired output</h3> <p><em>Script</em>:</p> <pre><code>SELECT d.dept_no , d.dept_name , COUNT(p.person_no) AS No_of_employees FROM Department d INNER JOIN Person p ON p.dept_no = d.dept_no GROUP BY d.dept_no , d.dept_name ORDER BY d.dept_no; </code></pre> <p><em>Output</em>:</p> <pre><code>DEPT_NO DEPT_NAME NO_OF_EMPLOYEES ------- --------- --------------- 1 Cleaner 4 2 Driver 3 3 Mechanic 6 </code></pre> <h3>Explanation</h3> <ul> <li><p>The query uses quite a few things like INNER JOIN, GROUP BY, COUNT and ORDER BY. Let's look each one of these.</p></li> <li><p><em>INNER JOIN</em> joins the tables based on the common field, in this case dept_no.</p></li> <li><p><em>COUNT</em> function would allow the query group all the count of employees by their department number and department name.</p></li> <li><p><code>COUNT</code> is an aggregate function. When you use an aggregate function with non-aggregate columns, then you need to use GROUP BY clause. Here the dept_no and dept_name are non-aggregate columns. <code>SUM</code>, <code>MAX</code>. <code>MIN</code> are some of the aggregate functions.</p></li> <li><p>Finally, we apply the <strong>ORDER BY</strong> clause to sort the output by <strong>dept_no</strong> column.</p></li> </ul> <h3>Demo</h3> <p><a href="http://sqlfiddle.com/#!4/c83fc/5" rel="nofollow noreferrer"><strong>Click here to view the demo in SQL Fiddle.</strong></a></p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload