This commit is contained in:
thomasabishop 2022-12-13 19:08:20 +00:00
parent 7180505ccc
commit d1889c8407
6 changed files with 153 additions and 122 deletions

View file

@ -1,97 +0,0 @@
---
categories:
- Databases
- Programming Languages
tags: [SQL]
---
# SQL: Joins
Once a relationship has been created using primary and foreign keys (as detailed in the previous section), you are able to combine and integrated data from the different tables. This is known as performing **joins.**
## Inner joins
We can demonstrate this with the following scenario:
> We want to create a list of the name of all computers that have been sold and when they were sold.
This will require us to use the `name` field from the `model` table and the `sale_date` field from the `sales` table.
Here's the SQL:
```sql
SELECT model.name, sales.sale_date
FROM model
INNER JOIN sales on model.model_id = sales.model_id;
```
- We use dot notation to distinguish the `table.field` for each table.
- We use `INNER JOIN` to join the `sales` table with the `model` table where `model_id` field in `model` is the same as the `model_id` field in `sales`
This returns:
```sql
name sale_date
-------------------- ----------
Raspberry Pi 2 Mo 4 2015-02-01
Raspberry Pi 3 Mo 4 2018-11-01
```
Note data will only be returned when there is a match between both fields stated in the `SELECT` clause. There must be corresponding data between `model.name` and `sale.sale_data` for a row to be returned. For example if there is a model that has not been sold, there will be a `mode.model_name` but no `sale_data` .
![](/img/model_sales_inner_join_step2.jpg)
## Outer joins
In the example above, we used the `INNER JOIN` method. This enshrines the logic:
> return only rows where there is a matching row in both tables
Which in the applied context means:
- If there is a model that has never been sold, it wont be returned
- If there is a sale without a model, it wont be returned
But there are other types of join that satisfy other types of logic.
The logical state that obtains in the case of **inner joins**:
![1_3.7-Inner_Join_Venn.png](/img/1_3.7-Inner_Join_Venn.png)
The logical state that obtains in the case of **left outer joins**
![](/img/2_3.7-Inner_Join_Left.png)
The logical state that obtains in the case of **right outer joins**:
![3_3.7-Inner_Join_Right.png](/img/3_3.7-Inner_Join_Right.png)
The logical state that obtains in the case of **full outer joins**:
![4_3.7-Full_Outer_Join.png](/img/4_3.7-Full_Outer_Join.png)
This type of join is used when you want to discern when there is _not_ a match between two fields across tables. For example: imagine that you wanted a list of computers that had never been sold. In this case, you would be interested in rows where there is a `model_id` without a corresponding `sales_id` .
In SQL this would be achieved with:
```sql
SELECT model.name, sales.sale_date
FROM model
LEFT JOIN sales on model.model_id = sales.model_id;
```
Note that this would return all the model names but where there isn't a sale data, `NULL` would be returned. This is an **important distinction :** the outer join method doesn't just return the rows with a `NULL` value for `sale_date` as we might expect. It returns all models along with those that have not been sold. This is because it is oriented to the "left" table, equivalent to the table in the SQL that we cited first with the `on` keyword.
> A left outer join returns all the records from the left (model) table and those that match in the right (sales) table. Where there are no matching records in the right (sales) table, a `NULL` value is returned.
A **right outer join**, often referred to as a right join, is the opposite of a left outer; it returns all the records from the right table and those that match in the left table. In our scenario this would be all the models that had a `sale_date` including models that didn't have a `sale_date` , i.e which returned `NULL`
Finally, a **full outer join** returns all the records from both tables, and where a record cannot be matched, a NULL value is returned. So this would mean there could be `NULL`s in both fields of the returned rows.
We can combine multiple types of join in the same SQL query:
```sql
SELECT model.name, sales.sale_date, manufacturer.url
FROM model
LEFT JOIN sales on model.model_id = sales.model_id
INNER JOIN manufacturer on model.manufacturer_id = manufacturer.manufacturer_id;
```

View file

@ -5,7 +5,9 @@ categories:
tags: [SQL]
---
# SQL Aggregate functions
# Aggregate functions in SQL
Aggregate functions enable us to return data about the data that a table holds. For example the sum of a given column or its average.
## Count return with custom variable

View file

@ -45,11 +45,17 @@ Here's our `returns` table:
| 7899 | 1 | 2020-11-218 | New device issued under warranty due to defect |
| 6711 | 2 | 2022-09-02 | Returned gift |
n this table `saleId` is identical to `saleId` in sales. It is the primary key in `sales` but a foreign key in `returns`. There is a one-to-one correspondance at work here. If a device has been returned it must have an entry in `returns` and the `salesId` of the entry in `returns` must match the `salesId` in `sales`.
In this table `saleId` is identical to `saleId` in sales. It is the primary key in `sales` but a foreign key in `returns`. If a device has been returned it must have an entry in `returns` and the `salesId` of the entry in `returns` must match the `salesId` in `sales`.
We already have the `sales` table. We want to create new table called `returns` that will sustain a one-to-one relationship with `sales`. We are going to use the `sale_id` as our foreign key in `returns`. This is the primary key in `sales`.
This is the primary benefit of utilising foreign keys: they add a restriction. Entries to the table with a foreign key **must** have a value that corresponds with the foreign key column.
We establish this with the following SQL:
We call this a **foreign key contraint**. More explicitly, our contraint is as follows:
> Any value entered into returns.saleId must already exist in sales.salesId
A secondary benefit is that they save us the trouble of repeating data. Without foreign keys we would have to input `saleId` twice in two different tables.
We establish the foreign key reference with ther following SQL:
```sql
CREATE TABLE returns (
@ -60,21 +66,6 @@ CREATE TABLE returns (
FOREIGN KEY (sale_id) REFERENCES sales(sale_id)
);
```
A table can have more than one foreign key.
https://www.cockroachlabs.com/blog/what-is-a-foreign-key/
---
Here's an example with more than one foreign key:
```sql
CREATE TABLE returns (
return_id integer PRIMARY KEY,
sale_id integer NOT NULL,
employee_id text NOT NULL,
date_returned text,
reason text,
FOREIGN KEY(sale_id) REFERENCES sales(sale_id),
FOREIGN KEY(employee_id) REFERENCES employee(employee_id)
);
```
If you delete the source of the foreign key, you also delete its references in tables for which it is a foreign key. This is important to remember. So if a row was deleted from `sales` the row in `returns` with the corresponding `saleId` would also be deleted.

View file

@ -0,0 +1,133 @@
---
categories:
- Databases
- Programming Languages
tags: [SQL]
---
# Joins in SQL
<!-- Once a relationship has been created using primary and foreign keys (as detailed in the previous section), you are able to combine and integrate data from the different tables. This is known as performing **joins.** -->
We perform joins in SQL when we combine and integrate data from multiple tables. In order for a join to be possible, **the tables you want to join must have rows that share the same fields**.
The output will be represented as a table but it is virtual, not an actual table. (If you wish to actually create a table or a view off the back of a join operation you should combine the join with the [`CREATE TABLE`](/Databases/SQL/Create_an_SQL_table.md) command etc.)
## Inner joins
> An inner join combines rows that have matching values in two or more tables. This join is based on the existence of a common field between the tables and is used to retrieve data that appears in both tables.
The following is a good scenario for creating an inner join:
> We want to create a list of the name of all computers that have been sold and when they were sold.
We will be working from the following tables.
_The `sales` table_:
| saleId | modelId | saleDate | employeeId | price |
| ------ | ------- | ---------- | ---------- | ------ |
| 1 | 44 | 2020-07-27 | tbishop | 40.99 |
| 2 | 22 | 2021-02-05 | tbishop | 986.99 |
| 3 | 14 | 2022-11-16 | tgnomay | 1248.99|
_The `model` table_:
| modelId | modelName |
| ------ | --------------------- |
| 44 | Raspberry Pi Model A |
| 22 | Apple MacBook Air |
| 14 | Lenovo ThinkPad P15 |
The data points we need are not provided in a single table. `sales` gives us the `saleDate` but not the `modelName`. In order to meet our requirements we must perform a join that combines `modelName` from the `model` table and `saleDate` from the `sale` table to give us a table like the following:
| modelName | sale_date |
| ------------------- |-----------|
| Raspberry Pi Model A | 2015-02-01|
| Apple Macbook Air | 2018-11-01|
| Lenovo ThinkPad P15 | 2018-11-01|
We can do this by utilising the field they have in common: `modelId`.
### Implementation
The general syntax for creating an inner join from two tables that share a common field is as follows:
```sql
SELECT column_name(s)
FROM table1
INNER JOIN table2
ON table1.columnName = table2.columnName
```
So basically, look at `table1` and `table2` return the rows where the fields for `table1` and `table2` match, where these fields are the ones specified in the `SELECT`.
Applied to our example:
```sql
SELECT model.modelName, sales.saleDate -- Name the fields
FROM model -- Specify the first table
INNER JOIN sales -- Specify the second table
ON model.model_id = sales.model_id; -- Specify the match criteria
```
> It is important to note that the match must _be_ a match. Both tables must have a row with the same value for `modelId` for the join to be applied. If there is a `modelId` of X in `sales` but no corresponding X for `modelId` in `model`, nothing will be returned for that row.
We can represent the logical relationship that obtains between the `sales` and `model` tables as follows:
![](/img/sql-inner-join-venn.png)
## Outer joins
Outer joins are joins that return matched values **and unmatched** values from either or both tables.
### Left outer join
A left outer join returns all records from the left or first table and the matching records from the right or second table. If there are not matches on the right then only the left data is returned.
### Right outer join
This is the inverse of the right outer join. A right outer join returns all records from the right or second table and the matching records from the left or first table. If there are not matches on the left then only the right data is returned.
### Full outer join
The full outer join returns all rows when there is a match in either the left or the right table. So, for table A and table B the full join returns all rows in A and all rows in B
The logical state that obtains in the case of **left outer joins**
![](/img/2_3.7-Inner_Join_Left.png)
The logical state that obtains in the case of **right outer joins**:
![3_3.7-Inner_Join_Right.png](/img/3_3.7-Inner_Join_Right.png)
The logical state that obtains in the case of **full outer joins**:
![4_3.7-Full_Outer_Join.png](/img/4_3.7-Full_Outer_Join.png)
This type of join is used when you want to discern when there is _not_ a match between two fields across tables. For example: imagine that you wanted a list of computers that had never been sold. In this case, you would be interested in rows where there is a `model_id` without a corresponding `sales_id` .
In SQL this would be achieved with:
```sql
SELECT model.name, sales.sale_date
FROM model
LEFT JOIN sales on model.model_id = sales.model_id;
```
Note that this would return all the model names but where there isn't a sale data, `NULL` would be returned. This is an **important distinction :** the outer join method doesn't just return the rows with a `NULL` value for `sale_date` as we might expect. It returns all models along with those that have not been sold. This is because it is oriented to the "left" table, equivalent to the table in the SQL that we cited first with the `on` keyword.
> A left outer join returns all the records from the left (model) table and those that match in the right (sales) table. Where there are no matching records in the right (sales) table, a `NULL` value is returned.
A **right outer join**, often referred to as a right join, is the opposite of a left outer; it returns all the records from the right table and those that match in the left table. In our scenario this would be all the models that had a `sale_date` including models that didn't have a `sale_date` , i.e which returned `NULL`
Finally, a **full outer join** returns all the records from both tables, and where a record cannot be matched, a NULL value is returned. So this would mean there could be `NULL`s in both fields of the returned rows.
We can combine multiple types of join in the same SQL query:
```sql
SELECT model.name, sales.sale_date, manufacturer.url
FROM model
LEFT JOIN sales on model.model_id = sales.model_id
INNER JOIN manufacturer on model.manufacturer_id = manufacturer.manufacturer_id;
```

View file

@ -26,9 +26,11 @@ The possible state changes for the JK Flip-Flop are detailed below:
| 1 | 0 | Pulse | 1 | Set |
| 1 | 1 | Pulse | Inverse of previous value | Toggle |
A JK Flip-Flop can execute on either the positive or negative pulse. Below are the diagrams fora rising and falling pulse respectively:
A JK Flip-Flop can execute on either the positive or negative pulse. Below are the diagrams for a rising and falling pulse respectively:
![](/img/jk-flip-flops.png)
// TODO diagram of JK Flipflop
## T Flip-Flops
@ -41,4 +43,4 @@ Thus the state table for the T Flip-Flop is:
| 0 | Pulse | Maintain previous value | Hold |
| 0 | Pulse | Inverse of previous value | Toggle |
// TODO: Add diagram
![](/img/t-flip-flops.png)

View file

@ -44,7 +44,7 @@ If we look at the pattern of each flip-flops' output we notice the following:
This means that to construct a circuit that displays this behaviour we just have to use a [T flip-flop](/Electronics_and_Hardware/Digital_circuits/Flip_flops.md#t-flip-flops) since the only state change we need is a single bit toggle three times that retains its value.
Using these pulse patterns we can construct a circuit as follows:
![](/img/3-bit-adder-diagram.png)
<iframe src="https://circuitverse.org/simulator/embed/3-bit-counter-d33846e3-7538-427d-b4cc-dc64fdaf0af3?theme=default&display_title=false&clock_time=true&fullscreen=true&zoom_in_out=true" style="border-width:; border-style: solid; border-color:;" name="myiframe" id="projectPreview" scrolling="no" frameborder="1" marginheight="0px" marginwidth="0px" height="500" width="600" allowFullScreen></iframe>