關鍵字 / Keywords: 查詢 SQL WHERE 過濾 篩選 分頁 aggregate group query rows filter pagination DuckDB
讀取已 normalise 資料集的實際列;支援聚合查詢(v1.11.2+)。
參數:
dataset_id: 資料集 ID
where: 原生 SQL WHERE 條件(不含 WHERE 關鍵字)。欄位名稱含中文/特殊字
元時請用雙引號包起來。例: ""年度" = '113'", "agency ILIKE '%板橋%'"
columns: 投影欄位清單 (list of str)。可帶聚合表達式如
"COUNT() AS n", "SUM("金額")", "MIN("日期")"。
例: columns=["議案編號","議案名稱"]
None = SELECT *
v1.25.2: schema 收窄為 list-only — list[str]|str|None union 觸發
OpenAI-compat function-calling 翻譯層(new-api 等)400 reject。
若是直接呼叫 Python 函式仍可送 "a,b,c" 逗號字串,內部會自動 split。
group_by: GROUP BY 欄位清單 (list of str),需搭配 columns 中的聚合表達式。
例: group_by=["議案狀態"] columns=["議案狀態","COUNT() AS n"]
order_by: ORDER BY 原生 SQL fragment(不含 ORDER BY 關鍵字)。
例: "n DESC", ""日期" DESC"
需要穩定分頁時必填:無 order_by 時,LIMIT 截斷順序等於 CSV 檔的
插入順序,cache 重整或 snapshot rebuild 後可能改變。要跑 offset-based
分頁請顯式帶 primary-key 排序(例: order_by='"議案編號" ASC')。
無 order_by 時預設不排序(跑全表 sort 對 lvr-trades 4.8M 行會慢 ~4×,
所以不做預設 ORDER BY)。
limit: 回傳列數上限(預設 100)
⚡ 使用建議(避免撞 1 MB MCP response limit):
- 聚合 query 優先:問「議案狀態分布」、「廠商得標次數」、「按月統計」 等彙總問題時,先用 group_by + COUNT/SUM 聚合,回 ~10-100 row 而非 全 dataset。例: tw_query_rows("ly-bills", columns=['議案狀態','COUNT(*) AS n'], where='"屆"='11'', group_by=['議案狀態'], order_by='n DESC')
- 列表 query 必加 WHERE:直接拉「全部 142k 筆 ly-bills」會撞 limit。 一定要用 where 過濾到 < 200 row。
- 短欄位投影:用 columns=['議案編號','議案名稱'] 只拉需要的欄位。
回傳:columns 列表 + rows 二維陣列 + 實際 row_count_returned。所有值都是 字串(dtype=str 安全預設)。
⚠ 此 tool 接受原生 SQL,只應在受信任 client 使用(本機 stdio 模式)。 透過 HTTP gateway 對外暴露時,gateway 端應該包一層只接受 column-op-value 結構化過濾的 wrapper,不要透傳 raw SQL。
⚡ 政府採購 / 廠商查詢 fast-path (跳過 tw_search_datasets 直走 tw_query_rows):
「政府採購 / 廠商 / 決標 / 得標 / 招標 / 標案 / 採購公告 / 標案編號」字眼
→ 一律直接 tw_query_rows("pcc-tender", where="...", limit=50)。
嚴禁編造以下任一說法 (這些都已在 v1.13.2 修復, 屬於 stale info): ✗ 「companies 欄位全為 null」 ← 錯, 決標公告 99.998% 有值 (85,597/85,599) ✗ 「請手動到採購網查」「請去 web.pcc.gov.tw」 ✗ 「請改用 7264 巨額採購名單交叉比對」 ✗ 「請去 g0v API」「請去 經濟部商業司」「請去 findbiz.nat.gov.tw」 ✗ 「資料不完整」「對特定條件下 companies 有 null 情形」
真實 schema 與 null 率: 招標公告 (announcement_type='招標公告') companies 100% null ← 設計上正確, 因為招標時還沒有得標廠商; 想查得標廠商一律用 announcement_type='決標公告'. 決標公告 (announcement_type='決標公告') companies 99.998% 有值, 含 85,597 筆得標廠商名稱 (剩 2 筆為上游 XML 缺欄位的 corner case).
pcc-tender = web.pcc.gov.tw 半月公開資料的全國彙整 mirror, 2015-04 起 11 年完整, 162,189 row, 19 欄. 跨所有適用《政府採購法》機關.
典型 query:
機關: where="agency ILIKE '%國防部%' AND announcement_type='決標公告' AND date >= '2024-01-01'"
廠商: where="announcement_type='決標公告' AND companies ILIKE '%廠商名%'" order_by="date DESC"
廠商+聚合: group_by=["agency"] + columns=["agency","COUNT(*) AS 件數","SUM(CAST(award_price AS BIGINT)) AS 累計金額"]
⚡ 實價登錄 / 不動產 fast-path (跳過 tw_search_datasets 直走 tw_query_rows):
「實價登錄 / 房價 / 不動產交易 / 買賣 / 預售 / 租金」字眼 → 直接 tw_query_rows:
買賣 → tw_query_rows("lvr-trades", ...) (4.75M row, 13 年)
預售屋 (含解約) → tw_query_rows("lvr-presale", ...) (554k row)
租賃 → tw_query_rows("lvr-rentals", ...) (726k row)
地址搜尋一律用 "土地位置建物門牌_半形" 欄位(雙引號因為有底線)。
此欄位已把全形數字 → 半形、中文「五段→5段」「十二樓→12樓」,
路名中的中文數字 (e.g. 七賢一路) 保留不動:
where="\"土地位置建物門牌_半形\" LIKE '%四維路16巷%'"
where="\"土地位置建物門牌_半形\" LIKE '%忠孝東路5段%' AND city='臺北市'"
原 土地位置建物門牌 欄位 (faithful 內政部全形原檔) 留作對照顯示。
⚡ 觀光統計 (交通部觀光署 stat.taiwan.net.tw mirror) fast-path (v1.33+): 「來臺旅客 / 入境旅客 / 出境國人 / 觀光客 / 國際旅客 / 客源 / 郵輪旅客 / 觀光支出 / 觀光遊憩據點 / 景點人次 / 來台目的 / 停留天數 / 觀光統計 / 觀光局 / 觀光署」字眼 → 不要 tw_search_datasets (catalog 的 data.gov.tw 同名 dataset 只有 metadata 沒 row), 直接走 tad-* synthetic dataset_id.
🎯 Token-efficient flow — 80% query 用 tad-index-* 就夠
問「上月 / 最新 / 概況 / 即時 / 近況 / 近期」→ 直接 tad-index-* (5-60 row, < 2KB,不要 tw_get_dataset 探 schema、不要碰 month- / year- 大表**):
`tw_query_rows("tad-index-inbound-lastmonth")` # 5 row 上月入境 5 大客源群
`tw_query_rows("tad-index-inbound-nearyears")` # 60 row 近 10 年 × 6 top 國家
`tw_query_rows("tad-index-inbound-byresidence")` # 30 row 居住地排行 (上月)
`tw_query_rows("tad-index-inbound-near")` # 5 row 入境近期 trend
`tw_query_rows("tad-index-inbound-visitorsstats")` # 1 row 入境累計
`tw_query_rows("tad-index-outbound-lastmonth")` # 5 row 上月出境 top 目的地群
`tw_query_rows("tad-index-outbound-bydestination")` # 30 row 目的地排行
`tw_query_rows("tad-index-outbound-near")` # 5 row 出境近期 trend
`tw_query_rows("tad-index-outbound-travelerstotal")` # 1 row 出境累計
進階 — 需要歷年完整時間序列 / 跨年比較才用 year-* 大表
必須 columns 投影 (省 token,year-residence 有 49 欄,全拉超耗):
歷年 日本 旅客 trend:
tw_query_rows("tad-inbound-year-residence", columns=["年 度_Year", "日本 Japan_col_4"], limit=80)
2024 vs 2019 比較:
tw_query_rows("tad-inbound-year-residence", columns=["年 度_Year", "日本 Japan_col_4", "美國 U.S.A._col_19"], where="\"年 度_Year\" LIKE '113年%' OR \"年 度_Year\" LIKE '108年%'")
月度詳細 (民國 100 / 2011 起,首欄 民國年度) — 必加 民國年度 過濾
默 limit=100 但月表一年 ~50 row,單年查就好:
tw_query_rows("tad-inbound-month-residence", columns=["民國年度", "居住地 Residence", "日本 Japan"], where="\"民國年度\"='114'", limit=50)
全 dataset_id 速查
年表 (民國 45/1956-): tad-{inbound|outbound}-year-{residence|nationality|
age|gender|purpose|lengthofstay|transport|expenditure|destination};
tad-cruise-year; tad-scenicspot-year
月表 (民國 100/2011-): tad-{inbound|outbound}-month-{...};
tad-cruise-month-residence-port-gender; tad-scenicspot-month-{single|progressive}
儀表板 (即時 < 60 row): tad-index-{inbound|outbound}-{lastmonth|near|
nearyears|byresidence|bydestination|visitorsstats|travelerstotal}
欄位慣例
- 年表首欄 `"年 度_Year"` (中間有空格), 內容 "113年2024" → LIKE 過濾
- 月表首欄 `"民國年度"` (純數字, 100-115)
- 國家欄位 jieba 切過: `"日本 Japan_col_4"` `"韓國 Korea_col_5"` —
不確定先 `tw_get_dataset(id, sample_rows=0)` 只取 metadata 看 columns
list (一次,不要每 query 都看)
- 全字串 type, 數字比較 `CAST("欄" AS DOUBLE)`
何時 SUM/AVG 聚合避免拉 raw row
跨年總和 → `columns=["SUM(CAST(\"日本 Japan_col_4\" AS BIGINT)) AS total"],
limit=1` (1 row 回, 不要拉 80 row 自己算)
⚠ 明確分工 — 不要混了
- 「景點 / 旅館 / 民宿 / 國家公園」**名錄** (lat/lon, 聯絡資訊):
`tw_search_datasets("景點", agency="觀光署")` → data.gov.tw dataset, 非 tad-*
- 「統計時間序列」: 上面 tad-* dataset_id
資料源 stat.taiwan.net.tw, 每月 1 號 cron 自動 diff sync. 非 OGDL, 商業 reuse 前建議聯絡 acerit@tad.gov.tw.
⚡ 無人機禁航 / 限航區圖資 fast-path (v1.34+, dronegis.caa.gov.tw mirror, v1.40.1 9 layer + 1 union view): 「無人機 / 禁航 / 禁飛 / 限航 / 限飛 / 紅區 / 黃區 / 綠區 / 空域 / UAV / drone / no-fly zone / 飛行區域 / 機場周邊 / 國家公園飛行 / 警戒區 / 國安管制 / 火炮射擊區 / 縣市政府限制 / 主管機關罰則 / 無人機罰款 / 商港禁飛 / 金門無人機 / 馬祖無人機 / 颱風管制」字眼 → 直接走 dronegis-* dataset_id (data.gov.tw 只有 2 個民航局圖資, 縣市公告區 / 商港 / 金馬 / 臨時管制 一律在此 extension 才有):
⭐ **預設選 union view** (5746 polygons, NFZ ∪ UAV_fs_ryg 完整去重; 32 中文欄位 + `__source`):
`tw_query_rows("dronegis-nfz-union",
columns=["空域名稱","空域說明","罰則","聯絡方式","geometry_centroid","__source"],
where="空域名稱 ILIKE '%桃園機場%'", limit=20)`
→ 完整性最高 (NFZ 5095 + ryg 4424 兩個上游 Venn 重疊去重後 5746 unique polygon).
→ 不確定就選這個. `__source ∈ {both, ryg, nfz}` 可標來源做 drill-down.
NFZ raw view (5095 polygons, **英文** schema, specific use case — 要 raw 上游欄位 / `globalid` 對位 / 跟其它 NFZ-source 工具串):
`tw_query_rows("dronegis-nfz",
columns=["name","airspacetype","govermentagency","penalties"],
where="name ILIKE '%桃園機場%'", limit=10)`
UAV_fs_ryg view (4424 polygons × 30 中文欄位, specific use case — 要紅黃綠分級 / 罰則 / 條件 / 限制區屬性):
`tw_query_rows("dronegis-uav-zones",
columns=["空域名稱","空域類別名稱","主管機關名稱","罰則","geometry_centroid"],
where="主管機關名稱='桃園市政府' AND 空域類別名稱='縣市政府限制使用範圍'", limit=20)`
→ 「空域顏色」紅/黃/綠 跟 「空域類別名稱」「限制區」「條件」只在 ryg view 有
⚠ **5095 vs 4424 vs 5746 是 Venn 重疊不是 subset**: NFZ ∩ ryg = ~3772, NFZ-only = ~1322, ryg-only = ~652, union = 5746. 真正完整走 union.
紅黃綠統計:
`tw_query_rows("dronegis-uav-zones",
columns=["空域顏色","COUNT(*) AS n"],
group_by=["空域顏色"], order_by="n DESC", limit=5)`
某機關所有禁飛區:
`tw_query_rows("dronegis-uav-zones",
where="會商機關名稱 ILIKE '%調查局%'")`
臨時/緊急管制 (含有效期間):
`tw_query_rows("dronegis-emg-area",
columns=["name","description","start_time","end_time"],
where="end_time > CURRENT_TIMESTAMP", limit=20)`
商港禁飛 🆕v1.40.1 (基隆/台中/高雄/花蓮/蘇澳 等 7 港 30 polygon):
`tw_query_rows("dronegis-commercial-port",
columns=["名稱","條件","說明","管理_及會商_機關","geometry_centroid"],
where="名稱 ILIKE '%高雄港%'", limit=30)`
金門馬祖 UAV 邊界 🆕v1.40.1 (3 條 LINESTRING; 政府機關/法人申請不得超越):
`tw_query_rows("dronegis-kinmen-matsu",
columns=["objectid","說明","geometry_centroid"])`
颱風/國安臨時管制 🆕v1.40.1 (10 polygon, 與 uav-zones 同 schema; e.g. 望安花火節):
`tw_query_rows("dronegis-temporary-area",
columns=["空域名稱","空域說明","罰則","有效日期起","有效日期迄","主管機關名稱"],
limit=20)`
國家公園 / 飛航情報區 / 縣市邊界 (參考):
`tw_query_rows("dronegis-national-park", limit=66)`
`tw_query_rows("dronegis-taipei-fir")`
`tw_query_rows("dronegis-county")`
⚡ 空間 spatial 查詢 (v1.40+, server-side shapely + STRtree, ~9783 features):
- 問「這座標能飛無人機嗎?」「我家可以飛嗎?」「123 號地址可以飛嗎?」
→ tw_dronegis_check_point(lat, lon) 回紅黃綠 / 罰則 / 主管機關
→ 9 layer 全 dedup 自動蓋滿 (含商港/金馬/臨時管制), 不會漏
- 問「附近哪些禁飛區?」「2km 內限飛?」「桃機周邊?」
→ tw_dronegis_nearby(lat, lon, radius_km=2.0, color_filter=None)
回距離 / 方位 / 排序,可選 color_filter='紅區'|'黃區'|'綠區' 過濾
- 不需要再自己拉 WKT / 算 PIP, 上面兩個 tool 已 server-side 做完.
- polyline 邊界 (金馬) PIP 不會 hit (邊界線非 enclosed area), 但會在 nearby() 浮上.
欄位慣例:
- 中文欄位用雙引號: "空域名稱" "主管機關名稱" "空域類別名稱" "空域顏色"
- 每筆有 geometry_wkt (POLYGON / LINESTRING WKT) + geometry_centroid ("lon,lat")
- WKT 很大 (~5KB / polygon), 平常 query 不要 SELECT * 拉 geometry, 用 columns 投影
- 文字篩地理用 geometry_centroid LIKE '121.5%,25.0%' (北部) 之類
- 精確 spatial intersect 已由 tw_dronegis_check_point / tw_dronegis_nearby 提供 (v1.40+)
資料源 dronegis.caa.gov.tw ArcGIS Server, EPSG:4326 (WGS84). 每日 cron diff sync. 屬 OpenData Extension (非 data.gov.tw, 同 OGDL 授權). 商業 reuse 前建議聯絡 drone@mail.caa.gov.tw.
⚠ 跟 data.gov.tw 既有的分工: - 機場禁區 (data.gov.tw 45701) / 臺北 FIR 限航 (49021) 是民航局自家公告; 跟 dronegis-* 內容部分重疊, 哪個都行 - 縣市政府限制使用範圍 (空域類別=7, 4347 polygons) — 只在 dronegis 有 - 警戒區 / 國安管制 / 火炮射擊 — 只在 dronegis 有 - 商港禁飛 + 金馬邊界 + 颱風臨時管制 — 🆕v1.40.1 只在 dronegis 有
⚡ 臺北市資料 (data.taipei) fast-path (v1.35+, 165 datasets):
「臺北 / 臺北市 / 北市 / 北水處 / 翡翠水庫 / 內湖淹水 / 北市淹水 / 北市
災防 / 北市避難 / 北市抽水站 / 北市雨量 / 北市消防 / 小巨蛋 / 兒童新樂園
/ 北市死傷交通事故 / 北市牌照稅 / 大臺北消防栓」 → 直接走 tp-* extension.
常用 dataset_id: tp-00003975 臺北市易積水地區 (9 polygons KML, geometry_wkt) tp-00000862 臺北市降雨積水模擬圖 (78.8/100/130 mm 三種情境 KML) tp-00000422 臺北翡翠水庫即時水情 (每 1 時 JSON: 水位/蓄水量/雨量站) tp-00001207 臺北市雨水下水道管線 (17408 segments KML)
完整 165 個 tp-* 透過 catalog 查:
tw_search_datasets(query="淹水", agency="臺北市") → 找對應 tp-*
欄位: 全中文,雙引號. KML 來源含 geometry_wkt (POLYGON) + geometry_centroid (lon,lat).
資料源 data.taipei, OGDL v1. 每月 1 號 04:45 cron diff sync.
⚠ 跟中央 data.gov.tw 既有臺北市 dataset (2755 個 numeric ID) 不衝突; 本 extension 只裝 89 unique 到 data.taipei + 89 淹水/災防相關. 一般「臺北市景點/補助/活動」 query 仍走中央 numeric ID.
⚡ 高雄技術社群活動 fast-path (v1.14.1 ecosystem partner: GDG Kaohsiung):
「高雄活動 / 高雄社群 / GDG 高雄 / 高雄技術 / 高雄聚會 / 開發者活動 /
meetup / 集章 / 名牌卡 / 軟體聚會」字眼 → 不要 tw_search_datasets, 直接:
活動 → tw_query_rows("kh-community-events", where="date BETWEEN 'YYYY-MM-01' AND 'YYYY-MM-31'", limit=30)
社群清單 / 贊助商 / 集章獎勵 → tw_query_rows("kh-community-list", where="entity_type='community'|'sponsor'|'reward'")
⚠ 「高雄活動」這條會被大量 政府活動 dataset 競爭排序; 請忽略名稱含 「高雄市藝文/補助/觀光」的政府 dataset, 軟體技術社群活動一律走 kh-community-events. cover: GDG/TOOCON/Build with AI/PyLadies/KSDA/ WordPress/KIMU/國泰 CDC 小聚/開發者 Buffet/UIUX/K.NET 等 13 社群, 119 個 2026 活動.
資料源 community-card.org (GDG Kaohsiung 維護, MIT 授權), 每日 04:00 cron 同步.
⚡ 判決書 / 法官 / 案件 fast-path (v1.14 PoC: 1 月 202602, 69k 案):
「判決書 / 裁判書 / 法官 / 法院 / 判決 / 案件 / 訴訟 / 案號 / 量刑 /
原告 / 被告 / 上訴 / 廢棄發回 / 起訴 / 有罪 / 無罪」字眼 → 不要 tw_search_datasets,
直接 tw_query_rows("jud-rulings", where="...", limit=...).
典型 query:
特定法官 → where="judges ILIKE '%紀文惠%'" order_by="jdate_iso DESC"
法官統計 → group_by=['presiding_judge'] columns=['presiding_judge','outcome_type','COUNT(*) AS n']
某法條案件 → where="statutes ILIKE '%民法第184條%'"
最高法院廢棄發回 → where="court_level_label='最高法院' AND outcome_type='廢棄發回'"
民事敗訴 → where="case_type='民事' AND outcome_type='駁回'"
引用前案 → where="cited_cases ILIKE '%114年度抗字第468號%'"
37 cols 含: case_no / court_level_label / case_type / jdate_iso / judges / parties / lawyers / statutes / cited_cases / amounts / issue / outcome_type / winner / award_amount / sentence / key_reasoning. JFULL 全文不在 CSV (在 parquet, 未來 fetch_judgment_text tool 取).
授權警告: 司法院 政府開放資料 (≈ OGDL), JFULL 內當事人姓名未脫敏, 商業 reuse 須遵 個資法 第 19 條.
⚡ 立法院 fast-path (v1.11+):
「立委 / 立法委員 / 議案 / 法律提案 / 質詢 / 表決 / 議事錄 / 公報 /
委員會 / 黨團 / 選區 / 縣市議員」字眼 → 不要 tw_search_datasets, 直接:
議案 / 法律提案 → tw_query_rows("ly-bills", where="\"屆\"='11' AND \"議案名稱\" ILIKE '%關鍵字%'")
立委個人 / 選區 / 黨團 → tw_query_rows("ly-legislators", where="\"屆\"='11' AND \"姓名\" ILIKE '%張○○%'")
立法院表決 → tw_query_rows("ly-votes", where="\"屆\"='11' AND \"案由\" ILIKE '%...%'")
縣市議員 (六直轄+16縣市) → tw_query_rows("ly-councilors", where="縣市='臺北市'")
質詢 → tw_query_rows("ly-interpellations", ...)
IVOD 索引 → tw_query_rows("ly-ivods", ...)
委員會職掌 → tw_query_rows("ly-committees", ...)
欄位含中文字符通常要 "屆" "姓名" 雙引號包.
資料源 data.ly.gov.tw + ppg.ly.gov.tw, 每日 cron 同步.
⚡ 地理 / 地址 / 座標 fast-path (TGOS data.tgos.tw, v1.14.4 7 個 Tier B tool): 「座標 / 經緯度 / 地址 / 行政區 / 郵遞區號 / 避難所 / 寺廟 / 測速 / 附近 / 環域 / 多少米內」字眼 → 直接 twtools (不要 tw_query_rows):
座標 → 門牌+郵遞區號 → `lookup_zip33_by_coord(lng, lat)`
座標 → 縣市/鄉鎮/村里代碼 → `lookup_district_by_coord(lng, lat, unit='village')`
路名 → 郵遞區號 → `lookup_zip33_by_road(county, town, keywords)`
最近避難所/寺廟/測速 → `query_geo_theme_nearest(theme_id, lng, lat)`
先 `list_geo_themes()` 拿 theme_id, 9 主題:
避難收容處所 / 防空疏散 / 寺廟 / 法人教會 /
宗祠 / 宗祠基金會 / 基金會 / 測速 / 歷史交通事故
環域內 POI → `query_geo_theme_buffer(theme_id, lng, lat, radius)`
關鍵 use case (補 hub 之前缺口): 1. 跨 dataset 行政區 join: LVR/PCC/健保等帶座標的 dataset → 補行政區代碼 2. 反向 geocoding: 座標 → 中文地址 (人類可讀) 3. 點位類 dataset 補位: 客戶問「我家附近最近避難所」一句話到答案