<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Relation on Tarragon</title><link>https://tarrragon.github.io/blog/tags/relation/</link><description>Recent content in Relation on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Tue, 01 Sep 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/relation/index.xml" rel="self" type="application/rss+xml"/><item><title>Relational Algebra（關聯代數）</title><link>https://tarrragon.github.io/blog/backend/01-database/sql/knowledge-cards/relational-algebra/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/sql/knowledge-cards/relational-algebra/</guid><description>&lt;p>關聯代數是一組作用在 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/sql/knowledge-cards/relation/" data-link-title="Relation（關係）" data-link-desc="看到 SQL 教材說「組成一個關係」而不確定它指的是不是資料表時">relation&lt;/a> 上、產出 relation 的運算——relation 指一組欄位固定、由若干列構成的資料集合，資料表是它的一種，查詢途中的中間結果也是。運算有這幾個：挑列（選取）、挑欄（投影）、把兩份的每一列各配一次（&lt;a href="https://tarrragon.github.io/blog/backend/01-database/sql/knowledge-cards/cartesian-product/" data-link-title="Cartesian Product（笛卡兒積）" data-link-desc="看到 CROSS JOIN、或結果的列數遠多於預期時，查這個運算什麼時候會被展開">積&lt;/a>）、在積上面加條件挑出要留的（連接）、以及聯集、差集、更名。連接自己就是積加上選取的組合，同一層還有兩個這個分類反覆用到的導出運算——&lt;a href="https://tarrragon.github.io/blog/backend/01-database/sql/knowledge-cards/semi-join-and-anti-join/" data-link-title="Semi-join 與 Anti-join（半連接與反連接）" data-link-desc="看到 EXISTS 或 NOT EXISTS 時，查它在代數裡對應哪個運算、以及列數上限為什麼是左邊那張表的列數">半連接與反連接&lt;/a>，配起來之後只帶走左邊那一份。SQL 的子句是這些運算的一層語法外衣，而不是另一套獨立的規則。&lt;/p>
&lt;h2 id="封閉性是它最重要的性質">封閉性是它最重要的性質&lt;/h2>
&lt;p>每個運算的輸入是關係、輸出還是關係，所以運算可以一個接一個組下去，中間結果與來源表的地位相同。這一條買到兩件事：子查詢可以寫在任何接受關係的位置，而多層查詢的判讀方式是逐層看每一層的欄與列。&lt;/p>
&lt;p>它也解釋了為什麼&lt;a href="https://tarrragon.github.io/blog/backend/01-database/sql/knowledge-cards/outer-join/" data-link-title="Outer Join（外連接）" data-link-desc="想確認 LEFT / RIGHT / FULL 各自保護哪一側、或連接之後有些人從名單上消失時">外連接&lt;/a>的產物可以繼續當下一個連接的輸入——那份補了 NULL 的東西仍然是一個關係。&lt;/p>
&lt;h2 id="sql-與它並非一對一">SQL 與它並非一對一&lt;/h2>
&lt;p>SQL 在代數之上多了幾樣代數本身沒有的：重複的列（代數的關係是集合，SQL 的表允許重複，所以才需要 &lt;code>DISTINCT&lt;/code>）、&lt;a href="https://tarrragon.github.io/blog/backend/01-database/sql/knowledge-cards/null/" data-link-title="NULL（空值）" data-link-desc="查 NULL 在比較、計數與分組裡各自怎麼表現時">NULL&lt;/a> 與三值邏輯、以及排序。這幾樣正好是最容易讀錯的幾處，理由是它們不受代數的規則保護。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/sql/" data-link-title="SQL：這個語言為什麼長這樣" data-link-desc="SQL 的設計而不是它的語法表：子句為什麼這樣切、一個查詢該怎麼讀，以及代價落在哪裡">SQL 這個分類&lt;/a>講語意模型的那幾篇，判斷標準全部收在這一層：子句的先後、連接的左右、條件擺哪一邊、分組的鍵，每一項都是某個運算的組合規則，而不是設計者的偏好。知道規則從代數來，讀不熟的查詢時就有一個可以推的依據，不必靠記憶。&lt;/p>
&lt;p>同一套代數換一個介面就是 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/sql/knowledge-cards/dataframe/" data-link-title="DataFrame（資料框）" data-link-desc="SQL 教材拿 pandas 或資料框當對照時，查 DataFrame 是什麼、它與資料表差在哪">DataFrame&lt;/a>，那也是這兩者多數操作對得上的原因。&lt;/p>
&lt;h2 id="往下走">往下走&lt;/h2>
&lt;p>連接產出的新關係怎麼改變列數與空缺，在 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/sql/join-changes-rows-and-nulls/" data-link-title="SQL.6 連接之後的列數與空缺：列數膨脹、外連接補的 NULL 與三值邏輯" data-link-desc="連接讓聚合多算的機制與計數、加總、平均、中位數各自的修法，以及外連接補出來的 NULL 在 count、等號比較、NOT IN 與 NOT EXISTS 上的行為">SQL.6 連接之後的列數與空缺&lt;/a>。同一組操作在 SQL 與 DataFrame 兩個介面上的對應、以及對應斷掉的三個位置，在 &lt;a href="https://tarrragon.github.io/blog/programming/python/basic/08-data-analysis/same-relational-algebra/" data-link-title="8.4 SQL 子句與 pandas 方法的對應：篩選、連接、分組彙總、視窗函數，以及空值、索引與順序的語意差異" data-link-desc="SQL 與 DataFrame 共用的關聯代數、同一份資料上兩邊寫法的實測比對，以及照著逐句翻譯會靜默失準的位置">python 模組八 8.4&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>關聯代數是一組作用在 <a href="/blog/backend/01-database/sql/knowledge-cards/relation/" data-link-title="Relation（關係）" data-link-desc="看到 SQL 教材說「組成一個關係」而不確定它指的是不是資料表時">relation</a> 上、產出 relation 的運算——relation 指一組欄位固定、由若干列構成的資料集合，資料表是它的一種，查詢途中的中間結果也是。運算有這幾個：挑列（選取）、挑欄（投影）、把兩份的每一列各配一次（<a href="/blog/backend/01-database/sql/knowledge-cards/cartesian-product/" data-link-title="Cartesian Product（笛卡兒積）" data-link-desc="看到 CROSS JOIN、或結果的列數遠多於預期時，查這個運算什麼時候會被展開">積</a>）、在積上面加條件挑出要留的（連接）、以及聯集、差集、更名。連接自己就是積加上選取的組合，同一層還有兩個這個分類反覆用到的導出運算——<a href="/blog/backend/01-database/sql/knowledge-cards/semi-join-and-anti-join/" data-link-title="Semi-join 與 Anti-join（半連接與反連接）" data-link-desc="看到 EXISTS 或 NOT EXISTS 時，查它在代數裡對應哪個運算、以及列數上限為什麼是左邊那張表的列數">半連接與反連接</a>，配起來之後只帶走左邊那一份。SQL 的子句是這些運算的一層語法外衣，而不是另一套獨立的規則。</p>
<h2 id="封閉性是它最重要的性質">封閉性是它最重要的性質</h2>
<p>每個運算的輸入是關係、輸出還是關係，所以運算可以一個接一個組下去，中間結果與來源表的地位相同。這一條買到兩件事：子查詢可以寫在任何接受關係的位置，而多層查詢的判讀方式是逐層看每一層的欄與列。</p>
<p>它也解釋了為什麼<a href="/blog/backend/01-database/sql/knowledge-cards/outer-join/" data-link-title="Outer Join（外連接）" data-link-desc="想確認 LEFT / RIGHT / FULL 各自保護哪一側、或連接之後有些人從名單上消失時">外連接</a>的產物可以繼續當下一個連接的輸入——那份補了 NULL 的東西仍然是一個關係。</p>
<h2 id="sql-與它並非一對一">SQL 與它並非一對一</h2>
<p>SQL 在代數之上多了幾樣代數本身沒有的：重複的列（代數的關係是集合，SQL 的表允許重複，所以才需要 <code>DISTINCT</code>）、<a href="/blog/backend/01-database/sql/knowledge-cards/null/" data-link-title="NULL（空值）" data-link-desc="查 NULL 在比較、計數與分組裡各自怎麼表現時">NULL</a> 與三值邏輯、以及排序。這幾樣正好是最容易讀錯的幾處，理由是它們不受代數的規則保護。</p>
<h2 id="概念位置">概念位置</h2>
<p><a href="/blog/backend/01-database/sql/" data-link-title="SQL：這個語言為什麼長這樣" data-link-desc="SQL 的設計而不是它的語法表：子句為什麼這樣切、一個查詢該怎麼讀，以及代價落在哪裡">SQL 這個分類</a>講語意模型的那幾篇，判斷標準全部收在這一層：子句的先後、連接的左右、條件擺哪一邊、分組的鍵，每一項都是某個運算的組合規則，而不是設計者的偏好。知道規則從代數來，讀不熟的查詢時就有一個可以推的依據，不必靠記憶。</p>
<p>同一套代數換一個介面就是 <a href="/blog/backend/01-database/sql/knowledge-cards/dataframe/" data-link-title="DataFrame（資料框）" data-link-desc="SQL 教材拿 pandas 或資料框當對照時，查 DataFrame 是什麼、它與資料表差在哪">DataFrame</a>，那也是這兩者多數操作對得上的原因。</p>
<h2 id="往下走">往下走</h2>
<p>連接產出的新關係怎麼改變列數與空缺，在 <a href="/blog/backend/01-database/sql/join-changes-rows-and-nulls/" data-link-title="SQL.6 連接之後的列數與空缺：列數膨脹、外連接補的 NULL 與三值邏輯" data-link-desc="連接讓聚合多算的機制與計數、加總、平均、中位數各自的修法，以及外連接補出來的 NULL 在 count、等號比較、NOT IN 與 NOT EXISTS 上的行為">SQL.6 連接之後的列數與空缺</a>。同一組操作在 SQL 與 DataFrame 兩個介面上的對應、以及對應斷掉的三個位置，在 <a href="/blog/programming/python/basic/08-data-analysis/same-relational-algebra/" data-link-title="8.4 SQL 子句與 pandas 方法的對應：篩選、連接、分組彙總、視窗函數，以及空值、索引與順序的語意差異" data-link-desc="SQL 與 DataFrame 共用的關聯代數、同一份資料上兩邊寫法的實測比對，以及照著逐句翻譯會靜默失準的位置">python 模組八 8.4</a>。</p>
]]></content:encoded></item></channel></rss>