# SQLAlchemy 2.0(05)查詢資料(2-join)
###### tags: `python` `sqlalchemy`
[官方文件](https://docs.sqlalchemy.org/en/20/tutorial/data_select.html)
關聯式資料表的一個核心應用就是關聯,這雖然擺明是廢話但卻也是事實。兩張資料表之間應該如何關聯在一起就是這一篇文章主要說明的部份。
首先,我們已經知道要查詢一張資料表的某一個欄位可以這麼做:
```python
print(select(user_table.c.name))
```
如果同時查詢兩張資料表然後用著下面的表達式的話:
```python
print(select(user_table.c.name, address_table.c.email_address))
```
```
SELECT user_account.name, address.email_address
FROM user_account, address
```
這不是不行,只是這種作法變成是cross join,沒有任何條件的把所有排列組合弄出來,但這可能不是我們要的。我們有幾種方式可以做。
## join_from
```python=
print(
select(user_table.c.name, address_table.c.email_address).join_from(
user_table, address_table
)
)
```
```
SELECT user_account.name, address.email_address
FROM user_account JOIN address ON user_account.id = address.user_id
```
我們在建置資料表的時候設置好外來鍵,因此上面可以發現`join_from`是沒有特別的再去指定關聯欄位。
## join
```python=
print(select(user_table.c.name, address_table.c.email_address).join(address_table))
```
```
SELECT user_account.name, address.email_address
FROM user_account JOIN address ON user_account.id = address.user_id
```
採用join的情況是,右邊的部份就看你join那一個table,左邊的部份就是另一個沒有被用到的table。不過這樣的方式並不是很好,如果可以的話我們希望可以顯示的處理:
```python=
print(select(address_table.c.email_address).select_from(user_table).join(address_table))
```
上面範例中我們採用`select_from`來指定左表,然後再搭配`join`來關聯右表,一樣沒有特別指定關聯欄位,而是讓軟體直接根據外來鍵的設置去處理這部份。
:::info
官方特別給出一個`count`的範例:
```python
from sqlalchemy import func
print(select(func.count("*")).select_from(user_table))
```
```
SELECT count(:count_2) AS count_1
FROM user_account
```
:::
:::info
ORM的關聯會另外說明,而且基本都是在類別定義的時候就已經設置好了。
:::
當然,如果真的希望可以自行設置關聯欄位的話也是可以的,作法也非常直觀,直接在`join`的時候指定關聯欄位:
```python=
print(
select(address_table.c.email_address)
.select_from(user_table)
.join(address_table, user_table.c.id == address_table.c.user_id)
)
```
## outerjoin
上面的範例都是屬於`inner join`,如果要`left outer join`的話可以這麼做:
```python=
print(select(user_table).join(address_table, isouter=True))
```
```
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account LEFT OUTER JOIN address ON user_account.id = address.user_id
```
```PYTHON=
print(select(user_table).join(address_table, full=True))
```
```
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account FULL OUTER JOIN address ON user_account.id = address.user_id
```
值得注意的是,官方有特別提到並沒有實作`right outer join`,你自己把表對換一下順序就好了。
:::info
SQL also has a “RIGHT OUTER JOIN”. SQLAlchemy doesn’t render this directly; instead, reverse the order of the tables and use “LEFT OUTER JOIN”.
:::