From 8f412b1b22e85b69bfe78242cd10a1c34191ac72 Mon Sep 17 00:00:00 2001
From: Tsubasa SEKIGUCHI <oss@tinykitten.me>
Date: Tue, 9 Dec 2025 16:44:31 +0000
Subject: [PATCH 1/2] =?UTF-8?q?=E5=90=8D=E5=89=8D=E6=A4=9C=E7=B4=A2?=
 =?UTF-8?q?=E3=81=A7ID=E3=81=8C=E8=A2=AB=E3=82=89=E3=81=AA=E3=81=84?=
 =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ...d1aaa9d6a8e3705162b694ac4d34bf5b4fbe.json} |   4 +-
 .../src/infrastructure/station_repository.rs  | 197 +++++++++---------
 2 files changed, 103 insertions(+), 98 deletions(-)
 rename .sqlx/{query-323d5e8a03e7c905970e1787748510402a5d36c1166f2d21cf14a100779048d6.json => query-c2be68e8c91643032540456639f9d1aaa9d6a8e3705162b694ac4d34bf5b4fbe.json} (57%)

diff --git a/.sqlx/query-323d5e8a03e7c905970e1787748510402a5d36c1166f2d21cf14a100779048d6.json b/.sqlx/query-c2be68e8c91643032540456639f9d1aaa9d6a8e3705162b694ac4d34bf5b4fbe.json
similarity index 57%
rename from .sqlx/query-323d5e8a03e7c905970e1787748510402a5d36c1166f2d21cf14a100779048d6.json
rename to .sqlx/query-c2be68e8c91643032540456639f9d1aaa9d6a8e3705162b694ac4d34bf5b4fbe.json
index 733d0a99..1a1598db 100644
--- a/.sqlx/query-323d5e8a03e7c905970e1787748510402a5d36c1166f2d21cf14a100779048d6.json
+++ b/.sqlx/query-c2be68e8c91643032540456639f9d1aaa9d6a8e3705162b694ac4d34bf5b4fbe.json
@@ -1,6 +1,6 @@
 {
   "db_name": "PostgreSQL",
-  "query": "WITH from_stations AS (\n                SELECT\n                    s.station_cd,\n                    s.line_cd\n                FROM stations AS s\n                WHERE s.station_g_cd = $1\n                AND s.e_status = 0\n            )\n            SELECT\n                s.station_cd,\n                s.station_g_cd,\n                s.station_name,\n                s.station_name_k,\n                s.station_name_r,\n                s.station_name_rn,\n                s.station_name_zh,\n                s.station_name_ko,\n                s.station_number1,\n                s.station_number2,\n                s.station_number3,\n                s.station_number4,\n                s.three_letter_code,\n                s.line_cd,\n                s.pref_cd,\n                s.post,\n                s.address,\n                s.lon,\n                s.lat,\n                s.open_ymd,\n                s.close_ymd,\n                s.e_status,\n                s.e_sort,\n                l.company_cd,\n                COALESCE(NULLIF(COALESCE(a.line_name, l.line_name), ''), NULL) AS line_name,\n                COALESCE(NULLIF(COALESCE(a.line_name_k, l.line_name_k), ''), NULL) AS line_name_k,\n                COALESCE(NULLIF(COALESCE(a.line_name_h, l.line_name_h), ''), NULL) AS line_name_h,\n                COALESCE(NULLIF(COALESCE(a.line_name_r, l.line_name_r), ''), NULL) AS line_name_r,\n                COALESCE(NULLIF(COALESCE(a.line_name_zh, l.line_name_zh), ''), NULL) AS line_name_zh,\n                COALESCE(NULLIF(COALESCE(a.line_name_ko, l.line_name_ko), ''), NULL) AS line_name_ko,\n                COALESCE(NULLIF(COALESCE(a.line_color_c, l.line_color_c), ''), NULL) AS line_color_c,\n                l.line_type,\n                l.line_symbol1,\n                l.line_symbol2,\n                l.line_symbol3,\n                l.line_symbol4,\n                l.line_symbol1_color,\n                l.line_symbol2_color,\n                l.line_symbol3_color,\n                l.line_symbol4_color,\n                l.line_symbol1_shape,\n                l.line_symbol2_shape,\n                l.line_symbol3_shape,\n                l.line_symbol4_shape,\n                COALESCE(l.average_distance, 0.0)::DOUBLE PRECISION AS average_distance,\n                COALESCE(from_sst.line_group_cd, NULL)::int AS line_group_cd, -- has_train_types用\n                NULL::int AS type_id,\n                NULL::int AS sst_id,\n                NULL::int AS type_cd,\n                NULL::int AS pass,\n                NULL::text AS type_name,\n                NULL::text AS type_name_k,\n                NULL::text AS type_name_r,\n                NULL::text AS type_name_zh,\n                NULL::text AS type_name_ko,\n                NULL::text AS color,\n                NULL::int AS direction,\n                NULL::int AS kind\n            FROM stations AS s\n                LEFT JOIN from_stations AS fs\n                    ON fs.station_cd IS NOT NULL\n                LEFT JOIN station_station_types AS from_sst\n                    ON from_sst.station_cd = fs.station_cd\n                LEFT JOIN station_station_types AS dst_sst\n                    ON dst_sst.station_cd = s.station_cd\n                LEFT JOIN types AS t\n                    ON t.type_cd = dst_sst.type_cd\n                LEFT JOIN line_aliases AS la\n                    ON la.station_cd = s.station_cd\n                LEFT JOIN aliases AS a\n                    ON la.alias_cd = a.id\n                JOIN lines AS l\n                    ON l.line_cd = s.line_cd\n                    AND l.e_status = 0\n            WHERE\n                (\n                    s.station_name   LIKE $2\n                    OR s.station_name_rn LIKE $3\n                    OR s.station_name_k LIKE $4\n                    OR s.station_name_zh LIKE $5\n                    OR s.station_name_ko LIKE $6\n                )\n                AND s.e_status = 0\n                AND (\n                    (\n                        from_sst.id IS NOT NULL\n                        AND dst_sst.id IS NOT NULL\n                        AND from_sst.line_group_cd = dst_sst.line_group_cd\n                        AND dst_sst.pass <> 1\n                    )\n                    OR\n                    (\n                        (from_sst.id IS NULL OR dst_sst.id IS NULL)\n                        AND s.line_cd = COALESCE(fs.line_cd, s.line_cd)\n                    )\n                )\n            ORDER BY s.station_g_cd, s.station_name\n            LIMIT $7",
+  "query": "WITH from_stations AS (\n                SELECT\n                    s.station_cd,\n                    s.line_cd\n                FROM stations AS s\n                WHERE s.station_g_cd = $1\n                AND s.e_status = 0\n            ),\n            filtered AS (\n                SELECT DISTINCT ON (s.station_cd)\n                    s.station_cd,\n                    s.station_g_cd,\n                    s.station_name,\n                    s.station_name_k,\n                    s.station_name_r,\n                    s.station_name_rn,\n                    s.station_name_zh,\n                    s.station_name_ko,\n                    s.station_number1,\n                    s.station_number2,\n                    s.station_number3,\n                    s.station_number4,\n                    s.three_letter_code,\n                    s.line_cd,\n                    s.pref_cd,\n                    s.post,\n                    s.address,\n                    s.lon,\n                    s.lat,\n                    s.open_ymd,\n                    s.close_ymd,\n                    s.e_status,\n                    s.e_sort,\n                    l.company_cd,\n                    COALESCE(NULLIF(COALESCE(a.line_name, l.line_name), ''), NULL) AS line_name,\n                    COALESCE(NULLIF(COALESCE(a.line_name_k, l.line_name_k), ''), NULL) AS line_name_k,\n                    COALESCE(NULLIF(COALESCE(a.line_name_h, l.line_name_h), ''), NULL) AS line_name_h,\n                    COALESCE(NULLIF(COALESCE(a.line_name_r, l.line_name_r), ''), NULL) AS line_name_r,\n                    COALESCE(NULLIF(COALESCE(a.line_name_zh, l.line_name_zh), ''), NULL) AS line_name_zh,\n                    COALESCE(NULLIF(COALESCE(a.line_name_ko, l.line_name_ko), ''), NULL) AS line_name_ko,\n                    COALESCE(NULLIF(COALESCE(a.line_color_c, l.line_color_c), ''), NULL) AS line_color_c,\n                    l.line_type,\n                    l.line_symbol1,\n                    l.line_symbol2,\n                    l.line_symbol3,\n                    l.line_symbol4,\n                    l.line_symbol1_color,\n                    l.line_symbol2_color,\n                    l.line_symbol3_color,\n                    l.line_symbol4_color,\n                    l.line_symbol1_shape,\n                    l.line_symbol2_shape,\n                    l.line_symbol3_shape,\n                    l.line_symbol4_shape,\n                    COALESCE(l.average_distance, 0.0)::DOUBLE PRECISION AS average_distance,\n                    COALESCE(from_sst.line_group_cd, NULL)::int AS line_group_cd, -- has_train_types用\n                    NULL::int AS type_id,\n                    NULL::int AS sst_id,\n                    NULL::int AS type_cd,\n                    NULL::int AS pass,\n                    NULL::text AS type_name,\n                    NULL::text AS type_name_k,\n                    NULL::text AS type_name_r,\n                    NULL::text AS type_name_zh,\n                    NULL::text AS type_name_ko,\n                    NULL::text AS color,\n                    NULL::int AS direction,\n                    NULL::int AS kind\n                FROM stations AS s\n                    LEFT JOIN from_stations AS fs\n                        ON fs.station_cd IS NOT NULL\n                    LEFT JOIN station_station_types AS from_sst\n                        ON from_sst.station_cd = fs.station_cd\n                    LEFT JOIN station_station_types AS dst_sst\n                        ON dst_sst.station_cd = s.station_cd\n                    LEFT JOIN types AS t\n                        ON t.type_cd = dst_sst.type_cd\n                    LEFT JOIN line_aliases AS la\n                        ON la.station_cd = s.station_cd\n                    LEFT JOIN aliases AS a\n                        ON la.alias_cd = a.id\n                    JOIN lines AS l\n                        ON l.line_cd = s.line_cd\n                        AND l.e_status = 0\n                WHERE\n                    (\n                        s.station_name   LIKE $2\n                        OR s.station_name_rn LIKE $3\n                        OR s.station_name_k LIKE $4\n                        OR s.station_name_zh LIKE $5\n                        OR s.station_name_ko LIKE $6\n                    )\n                    AND s.e_status = 0\n                    AND (\n                        (\n                            from_sst.id IS NOT NULL\n                            AND dst_sst.id IS NOT NULL\n                            AND from_sst.line_group_cd = dst_sst.line_group_cd\n                            AND dst_sst.pass <> 1\n                        )\n                        OR\n                        (\n                            (from_sst.id IS NULL OR dst_sst.id IS NULL)\n                            AND s.line_cd = COALESCE(fs.line_cd, s.line_cd)\n                        )\n                    )\n                ORDER BY s.station_cd, s.station_g_cd, s.station_name\n            )\n            SELECT *\n            FROM filtered\n            ORDER BY station_g_cd, station_name\n            LIMIT $7",
   "describe": {
     "columns": [
       {
@@ -366,5 +366,5 @@
       null
     ]
   },
-  "hash": "323d5e8a03e7c905970e1787748510402a5d36c1166f2d21cf14a100779048d6"
+  "hash": "c2be68e8c91643032540456639f9d1aaa9d6a8e3705162b694ac4d34bf5b4fbe"
 }
diff --git a/stationapi/src/infrastructure/station_repository.rs b/stationapi/src/infrastructure/station_repository.rs
index 359aaacb..28b337e8 100644
--- a/stationapi/src/infrastructure/station_repository.rs
+++ b/stationapi/src/infrastructure/station_repository.rs
@@ -959,105 +959,110 @@ impl InternalStationRepository {
                 FROM stations AS s
                 WHERE s.station_g_cd = $1
                 AND s.e_status = 0
-            )
-            SELECT
-                s.station_cd,
-                s.station_g_cd,
-                s.station_name,
-                s.station_name_k,
-                s.station_name_r,
-                s.station_name_rn,
-                s.station_name_zh,
-                s.station_name_ko,
-                s.station_number1,
-                s.station_number2,
-                s.station_number3,
-                s.station_number4,
-                s.three_letter_code,
-                s.line_cd,
-                s.pref_cd,
-                s.post,
-                s.address,
-                s.lon,
-                s.lat,
-                s.open_ymd,
-                s.close_ymd,
-                s.e_status,
-                s.e_sort,
-                l.company_cd,
-                COALESCE(NULLIF(COALESCE(a.line_name, l.line_name), ''), NULL) AS line_name,
-                COALESCE(NULLIF(COALESCE(a.line_name_k, l.line_name_k), ''), NULL) AS line_name_k,
-                COALESCE(NULLIF(COALESCE(a.line_name_h, l.line_name_h), ''), NULL) AS line_name_h,
-                COALESCE(NULLIF(COALESCE(a.line_name_r, l.line_name_r), ''), NULL) AS line_name_r,
-                COALESCE(NULLIF(COALESCE(a.line_name_zh, l.line_name_zh), ''), NULL) AS line_name_zh,
-                COALESCE(NULLIF(COALESCE(a.line_name_ko, l.line_name_ko), ''), NULL) AS line_name_ko,
-                COALESCE(NULLIF(COALESCE(a.line_color_c, l.line_color_c), ''), NULL) AS line_color_c,
-                l.line_type,
-                l.line_symbol1,
-                l.line_symbol2,
-                l.line_symbol3,
-                l.line_symbol4,
-                l.line_symbol1_color,
-                l.line_symbol2_color,
-                l.line_symbol3_color,
-                l.line_symbol4_color,
-                l.line_symbol1_shape,
-                l.line_symbol2_shape,
-                l.line_symbol3_shape,
-                l.line_symbol4_shape,
-                COALESCE(l.average_distance, 0.0)::DOUBLE PRECISION AS average_distance,
-                COALESCE(from_sst.line_group_cd, NULL)::int AS line_group_cd, -- has_train_types用
-                NULL::int AS type_id,
-                NULL::int AS sst_id,
-                NULL::int AS type_cd,
-                NULL::int AS pass,
-                NULL::text AS type_name,
-                NULL::text AS type_name_k,
-                NULL::text AS type_name_r,
-                NULL::text AS type_name_zh,
-                NULL::text AS type_name_ko,
-                NULL::text AS color,
-                NULL::int AS direction,
-                NULL::int AS kind
-            FROM stations AS s
-                LEFT JOIN from_stations AS fs
-                    ON fs.station_cd IS NOT NULL
-                LEFT JOIN station_station_types AS from_sst
-                    ON from_sst.station_cd = fs.station_cd
-                LEFT JOIN station_station_types AS dst_sst
-                    ON dst_sst.station_cd = s.station_cd
-                LEFT JOIN types AS t
-                    ON t.type_cd = dst_sst.type_cd
-                LEFT JOIN line_aliases AS la
-                    ON la.station_cd = s.station_cd
-                LEFT JOIN aliases AS a
-                    ON la.alias_cd = a.id
-                JOIN lines AS l
-                    ON l.line_cd = s.line_cd
-                    AND l.e_status = 0
-            WHERE
-                (
-                    s.station_name   LIKE $2
-                    OR s.station_name_rn LIKE $3
-                    OR s.station_name_k LIKE $4
-                    OR s.station_name_zh LIKE $5
-                    OR s.station_name_ko LIKE $6
-                )
-                AND s.e_status = 0
-                AND (
+            ),
+            filtered AS (
+                SELECT DISTINCT ON (s.station_cd)
+                    s.station_cd,
+                    s.station_g_cd,
+                    s.station_name,
+                    s.station_name_k,
+                    s.station_name_r,
+                    s.station_name_rn,
+                    s.station_name_zh,
+                    s.station_name_ko,
+                    s.station_number1,
+                    s.station_number2,
+                    s.station_number3,
+                    s.station_number4,
+                    s.three_letter_code,
+                    s.line_cd,
+                    s.pref_cd,
+                    s.post,
+                    s.address,
+                    s.lon,
+                    s.lat,
+                    s.open_ymd,
+                    s.close_ymd,
+                    s.e_status,
+                    s.e_sort,
+                    l.company_cd,
+                    COALESCE(NULLIF(COALESCE(a.line_name, l.line_name), ''), NULL) AS line_name,
+                    COALESCE(NULLIF(COALESCE(a.line_name_k, l.line_name_k), ''), NULL) AS line_name_k,
+                    COALESCE(NULLIF(COALESCE(a.line_name_h, l.line_name_h), ''), NULL) AS line_name_h,
+                    COALESCE(NULLIF(COALESCE(a.line_name_r, l.line_name_r), ''), NULL) AS line_name_r,
+                    COALESCE(NULLIF(COALESCE(a.line_name_zh, l.line_name_zh), ''), NULL) AS line_name_zh,
+                    COALESCE(NULLIF(COALESCE(a.line_name_ko, l.line_name_ko), ''), NULL) AS line_name_ko,
+                    COALESCE(NULLIF(COALESCE(a.line_color_c, l.line_color_c), ''), NULL) AS line_color_c,
+                    l.line_type,
+                    l.line_symbol1,
+                    l.line_symbol2,
+                    l.line_symbol3,
+                    l.line_symbol4,
+                    l.line_symbol1_color,
+                    l.line_symbol2_color,
+                    l.line_symbol3_color,
+                    l.line_symbol4_color,
+                    l.line_symbol1_shape,
+                    l.line_symbol2_shape,
+                    l.line_symbol3_shape,
+                    l.line_symbol4_shape,
+                    COALESCE(l.average_distance, 0.0)::DOUBLE PRECISION AS average_distance,
+                    COALESCE(from_sst.line_group_cd, NULL)::int AS line_group_cd, -- has_train_types用
+                    NULL::int AS type_id,
+                    NULL::int AS sst_id,
+                    NULL::int AS type_cd,
+                    NULL::int AS pass,
+                    NULL::text AS type_name,
+                    NULL::text AS type_name_k,
+                    NULL::text AS type_name_r,
+                    NULL::text AS type_name_zh,
+                    NULL::text AS type_name_ko,
+                    NULL::text AS color,
+                    NULL::int AS direction,
+                    NULL::int AS kind
+                FROM stations AS s
+                    LEFT JOIN from_stations AS fs
+                        ON fs.station_cd IS NOT NULL
+                    LEFT JOIN station_station_types AS from_sst
+                        ON from_sst.station_cd = fs.station_cd
+                    LEFT JOIN station_station_types AS dst_sst
+                        ON dst_sst.station_cd = s.station_cd
+                    LEFT JOIN types AS t
+                        ON t.type_cd = dst_sst.type_cd
+                    LEFT JOIN line_aliases AS la
+                        ON la.station_cd = s.station_cd
+                    LEFT JOIN aliases AS a
+                        ON la.alias_cd = a.id
+                    JOIN lines AS l
+                        ON l.line_cd = s.line_cd
+                        AND l.e_status = 0
+                WHERE
                     (
-                        from_sst.id IS NOT NULL
-                        AND dst_sst.id IS NOT NULL
-                        AND from_sst.line_group_cd = dst_sst.line_group_cd
-                        AND dst_sst.pass <> 1
+                        s.station_name   LIKE $2
+                        OR s.station_name_rn LIKE $3
+                        OR s.station_name_k LIKE $4
+                        OR s.station_name_zh LIKE $5
+                        OR s.station_name_ko LIKE $6
                     )
-                    OR
-                    (
-                        (from_sst.id IS NULL OR dst_sst.id IS NULL)
-                        AND s.line_cd = COALESCE(fs.line_cd, s.line_cd)
+                    AND s.e_status = 0
+                    AND (
+                        (
+                            from_sst.id IS NOT NULL
+                            AND dst_sst.id IS NOT NULL
+                            AND from_sst.line_group_cd = dst_sst.line_group_cd
+                            AND dst_sst.pass <> 1
+                        )
+                        OR
+                        (
+                            (from_sst.id IS NULL OR dst_sst.id IS NULL)
+                            AND s.line_cd = COALESCE(fs.line_cd, s.line_cd)
+                        )
                     )
-                )
-            ORDER BY s.station_g_cd, s.station_name
+                ORDER BY s.station_cd, s.station_g_cd, s.station_name
+            )
+            SELECT *
+            FROM filtered
+            ORDER BY station_g_cd, station_name
             LIMIT $7"#,
             from_station_group_id,
             station_name,

From fd44f9455d4c065866e44e858a6e761f4c1f453a Mon Sep 17 00:00:00 2001
From: Tsubasa SEKIGUCHI <oss@tinykitten.me>
Date: Wed, 10 Dec 2025 20:27:22 +0900
Subject: [PATCH 2/2] Merge pull request #1344 from
 TrainLCD/feature/via-line-id
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

get_route_stopsのvia_line_id対応
---
 ...f4944d4e572e97654fc65cb425e5435d337b.json} |  5 ++-
 ...502911473ecef28265350576cd8bee64f7f8.json} |  5 ++-
 stationapi/proto                              |  2 +-
 .../domain/repository/station_repository.rs   | 44 ++++++++++++++++---
 .../src/infrastructure/station_repository.rs  | 15 ++++++-
 .../src/presentation/controller/grpc.rs       | 21 +++++++--
 stationapi/src/use_case/interactor/query.rs   |  9 ++--
 stationapi/src/use_case/traits/query.rs       |  3 ++
 8 files changed, 86 insertions(+), 18 deletions(-)
 rename .sqlx/{query-217b99932d995eff26a2eb16abab5dd05c27b6b77f78f169ca2049f45cf432ce.json => query-20b55238238b1655930a5716441ff4944d4e572e97654fc65cb425e5435d337b.json} (98%)
 rename .sqlx/{query-422bdec51028a86db49d9e2b0babd7f58066d3a2433f5b6416972dfc359540fa.json => query-64004f2e2ea8f34594c230fe82d5502911473ecef28265350576cd8bee64f7f8.json} (60%)

diff --git a/.sqlx/query-217b99932d995eff26a2eb16abab5dd05c27b6b77f78f169ca2049f45cf432ce.json b/.sqlx/query-20b55238238b1655930a5716441ff4944d4e572e97654fc65cb425e5435d337b.json
similarity index 98%
rename from .sqlx/query-217b99932d995eff26a2eb16abab5dd05c27b6b77f78f169ca2049f45cf432ce.json
rename to .sqlx/query-20b55238238b1655930a5716441ff4944d4e572e97654fc65cb425e5435d337b.json
index 0a76dd3a..74dfa4da 100644
--- a/.sqlx/query-217b99932d995eff26a2eb16abab5dd05c27b6b77f78f169ca2049f45cf432ce.json
+++ b/.sqlx/query-20b55238238b1655930a5716441ff4944d4e572e97654fc65cb425e5435d337b.json
@@ -1,6 +1,6 @@
 {
   "db_name": "PostgreSQL",
-  "query": "WITH\n                from_cte AS (\n                    SELECT\n                        s.station_cd,\n                        s.line_cd\n                    FROM\n                        stations AS s\n                    WHERE\n                        s.station_g_cd = $1\n                        AND s.e_status = 0\n                ),\n                to_cte AS (\n                    SELECT\n                        s.station_cd,\n                        s.line_cd\n                    FROM\n                        stations AS s\n                    WHERE\n                        s.station_g_cd = $2\n                        AND s.e_status = 0\n                ),\n                sst_cte_c1 AS (\n                    SELECT\n                        sst.line_group_cd\n                    FROM\n                        station_station_types AS sst\n                        JOIN from_cte ON sst.station_cd = from_cte.station_cd\n                    WHERE\n                        sst.pass <> 1\n                ),\n                sst_cte_c2 AS (\n                    SELECT\n                        sst.line_group_cd\n                    FROM\n                        station_station_types AS sst\n                        JOIN to_cte ON sst.station_cd = to_cte.station_cd\n                    WHERE\n                        sst.pass <> 1\n                ),\n                sst_cte AS (\n                    SELECT\n                        sst.id,\n                        sst.station_cd,\n                        sst.type_cd,\n                        sst.line_group_cd,\n                        sst.pass\n                    FROM\n                        station_station_types AS sst\n                        JOIN sst_cte_c1 ON sst.line_group_cd = sst_cte_c1.line_group_cd\n                        JOIN sst_cte_c2 ON sst.line_group_cd = sst_cte_c2.line_group_cd\n                )\n            SELECT\n                sta.station_cd,\n                sta.station_g_cd,\n                sta.station_name,\n                sta.station_name_k,\n                sta.station_name_r,\n                sta.station_name_rn,\n                sta.station_name_zh,\n                sta.station_name_ko,\n                sta.station_number1,\n                sta.station_number2,\n                sta.station_number3,\n                sta.station_number4,\n                sta.three_letter_code,\n                sta.line_cd,\n                sta.pref_cd,\n                sta.post,\n                sta.address,\n                sta.lon,\n                sta.lat,\n                sta.open_ymd,\n                sta.close_ymd,\n                sta.e_status,\n                sta.e_sort,\n                lin.company_cd,\n                COALESCE(NULLIF(COALESCE(a.line_name, lin.line_name), ''), NULL) AS line_name,\n                COALESCE(NULLIF(COALESCE(a.line_name_k, lin.line_name_k), ''), NULL) AS line_name_k,\n                COALESCE(NULLIF(COALESCE(a.line_name_h, lin.line_name_h), ''), NULL) AS line_name_h,\n                COALESCE(NULLIF(COALESCE(a.line_name_r, lin.line_name_r), ''), NULL) AS line_name_r,\n                COALESCE(NULLIF(COALESCE(a.line_name_zh, lin.line_name_zh), ''), NULL) AS line_name_zh,\n                COALESCE(NULLIF(COALESCE(a.line_name_ko, lin.line_name_ko), ''), NULL) AS line_name_ko,\n                COALESCE(NULLIF(COALESCE(a.line_color_c, lin.line_color_c), ''), NULL) AS line_color_c,\n                lin.line_type,\n                lin.line_symbol1,\n                lin.line_symbol2,\n                lin.line_symbol3,\n                lin.line_symbol4,\n                lin.line_symbol1_color,\n                lin.line_symbol2_color,\n                lin.line_symbol3_color,\n                lin.line_symbol4_color,\n                lin.line_symbol1_shape,\n                lin.line_symbol2_shape,\n                lin.line_symbol3_shape,\n                lin.line_symbol4_shape,\n                COALESCE(lin.average_distance, 0.0)::DOUBLE PRECISION AS average_distance,\n                tt.id AS type_id,\n                sst.id AS sst_id,\n                sst.type_cd,\n                sst.line_group_cd,\n                sst.pass,\n                tt.type_name,\n                tt.type_name_k,\n                tt.type_name_r,\n                tt.type_name_zh,\n                tt.type_name_ko,\n                tt.color,\n                tt.direction,\n                tt.kind\n            FROM\n                stations AS sta\n                LEFT JOIN sst_cte AS sst ON sst.station_cd = sta.station_cd\n                JOIN types AS tt ON tt.type_cd = sst.type_cd\n                JOIN lines AS lin ON lin.line_cd = sta.line_cd AND lin.e_status = 0\n                LEFT JOIN line_aliases AS la ON la.station_cd = sta.station_cd\n                LEFT JOIN aliases AS a ON a.id = la.alias_cd\n            WHERE\n                sta.e_status = 0\n            ORDER BY sst.id",
+  "query": "WITH\n                from_cte AS (\n                    SELECT\n                        s.station_cd,\n                        s.line_cd\n                    FROM\n                        stations AS s\n                    WHERE\n                        s.station_g_cd = $1\n                        AND s.e_status = 0\n                ),\n                to_cte AS (\n                    SELECT\n                        s.station_cd,\n                        s.line_cd\n                    FROM\n                        stations AS s\n                    WHERE\n                        s.station_g_cd = $2\n                        AND s.e_status = 0\n                ),\n                sst_cte_c1 AS (\n                    SELECT\n                        sst.line_group_cd\n                    FROM\n                        station_station_types AS sst\n                        JOIN from_cte ON sst.station_cd = from_cte.station_cd\n                    WHERE\n                        sst.pass <> 1\n                ),\n                sst_cte_c2 AS (\n                    SELECT\n                        sst.line_group_cd\n                    FROM\n                        station_station_types AS sst\n                        JOIN to_cte ON sst.station_cd = to_cte.station_cd\n                    WHERE\n                        sst.pass <> 1\n                ),\n                sst_cte AS (\n                    SELECT\n                        sst.id,\n                        sst.station_cd,\n                        sst.type_cd,\n                        sst.line_group_cd,\n                        sst.pass\n                    FROM\n                        station_station_types AS sst\n                        JOIN sst_cte_c1 ON sst.line_group_cd = sst_cte_c1.line_group_cd\n                        JOIN sst_cte_c2 ON sst.line_group_cd = sst_cte_c2.line_group_cd\n                )\n            SELECT\n                sta.station_cd,\n                sta.station_g_cd,\n                sta.station_name,\n                sta.station_name_k,\n                sta.station_name_r,\n                sta.station_name_rn,\n                sta.station_name_zh,\n                sta.station_name_ko,\n                sta.station_number1,\n                sta.station_number2,\n                sta.station_number3,\n                sta.station_number4,\n                sta.three_letter_code,\n                sta.line_cd,\n                sta.pref_cd,\n                sta.post,\n                sta.address,\n                sta.lon,\n                sta.lat,\n                sta.open_ymd,\n                sta.close_ymd,\n                sta.e_status,\n                sta.e_sort,\n                lin.company_cd,\n                COALESCE(NULLIF(COALESCE(a.line_name, lin.line_name), ''), NULL) AS line_name,\n                COALESCE(NULLIF(COALESCE(a.line_name_k, lin.line_name_k), ''), NULL) AS line_name_k,\n                COALESCE(NULLIF(COALESCE(a.line_name_h, lin.line_name_h), ''), NULL) AS line_name_h,\n                COALESCE(NULLIF(COALESCE(a.line_name_r, lin.line_name_r), ''), NULL) AS line_name_r,\n                COALESCE(NULLIF(COALESCE(a.line_name_zh, lin.line_name_zh), ''), NULL) AS line_name_zh,\n                COALESCE(NULLIF(COALESCE(a.line_name_ko, lin.line_name_ko), ''), NULL) AS line_name_ko,\n                COALESCE(NULLIF(COALESCE(a.line_color_c, lin.line_color_c), ''), NULL) AS line_color_c,\n                lin.line_type,\n                lin.line_symbol1,\n                lin.line_symbol2,\n                lin.line_symbol3,\n                lin.line_symbol4,\n                lin.line_symbol1_color,\n                lin.line_symbol2_color,\n                lin.line_symbol3_color,\n                lin.line_symbol4_color,\n                lin.line_symbol1_shape,\n                lin.line_symbol2_shape,\n                lin.line_symbol3_shape,\n                lin.line_symbol4_shape,\n                COALESCE(lin.average_distance, 0.0)::DOUBLE PRECISION AS average_distance,\n                tt.id AS type_id,\n                sst.id AS sst_id,\n                sst.type_cd,\n                sst.line_group_cd,\n                sst.pass,\n                tt.type_name,\n                tt.type_name_k,\n                tt.type_name_r,\n                tt.type_name_zh,\n                tt.type_name_ko,\n                tt.color,\n                tt.direction,\n                tt.kind\n            FROM\n                stations AS sta\n                LEFT JOIN sst_cte AS sst ON sst.station_cd = sta.station_cd\n                JOIN types AS tt ON tt.type_cd = sst.type_cd\n                JOIN lines AS lin ON lin.line_cd = sta.line_cd AND lin.e_status = 0\n                LEFT JOIN line_aliases AS la ON la.station_cd = sta.station_cd\n                LEFT JOIN aliases AS a ON a.id = la.alias_cd\n            WHERE\n                sta.e_status = 0\n                AND ($3::int IS NULL OR sta.line_cd = $3)\n            ORDER BY sst.id",
   "describe": {
     "columns": [
       {
@@ -296,6 +296,7 @@
     ],
     "parameters": {
       "Left": [
+        "Int4",
         "Int4",
         "Int4"
       ]
@@ -361,5 +362,5 @@
       true
     ]
   },
-  "hash": "217b99932d995eff26a2eb16abab5dd05c27b6b77f78f169ca2049f45cf432ce"
+  "hash": "20b55238238b1655930a5716441ff4944d4e572e97654fc65cb425e5435d337b"
 }
diff --git a/.sqlx/query-422bdec51028a86db49d9e2b0babd7f58066d3a2433f5b6416972dfc359540fa.json b/.sqlx/query-64004f2e2ea8f34594c230fe82d5502911473ecef28265350576cd8bee64f7f8.json
similarity index 60%
rename from .sqlx/query-422bdec51028a86db49d9e2b0babd7f58066d3a2433f5b6416972dfc359540fa.json
rename to .sqlx/query-64004f2e2ea8f34594c230fe82d5502911473ecef28265350576cd8bee64f7f8.json
index 554e1ef0..36652345 100644
--- a/.sqlx/query-422bdec51028a86db49d9e2b0babd7f58066d3a2433f5b6416972dfc359540fa.json
+++ b/.sqlx/query-64004f2e2ea8f34594c230fe82d5502911473ecef28265350576cd8bee64f7f8.json
@@ -1,6 +1,6 @@
 {
   "db_name": "PostgreSQL",
-  "query": "WITH\n                from_cte AS (\n                    SELECT\n                        s.station_cd,\n                        s.line_cd\n                    FROM\n                        stations AS s\n                    WHERE\n                        s.station_g_cd = $1\n                ),\n                to_cte AS (\n                    SELECT\n                        s.station_cd,\n                        s.line_cd\n                    FROM\n                        stations AS s\n                    WHERE\n                        s.station_g_cd = $2\n                ),\n                common_lines AS (\n                    SELECT DISTINCT s1.line_cd\n                    FROM stations s1\n                    WHERE s1.station_g_cd = $3\n                        AND s1.e_status = 0\n                        AND EXISTS (\n                        SELECT 1\n                        FROM stations s2\n                        WHERE s2.station_g_cd = $4\n                            AND s2.e_status = 0\n                            AND s2.line_cd = s1.line_cd\n                        )\n                ),\n                sst_cte_c1 AS (\n                    SELECT\n                        sst.line_group_cd\n                    FROM\n                        station_station_types AS sst\n                        JOIN from_cte ON sst.station_cd = from_cte.station_cd\n                    WHERE\n                        sst.pass <> 1\n                ),\n                sst_cte_c2 AS (\n                    SELECT\n                        sst.line_group_cd\n                    FROM\n                        station_station_types AS sst\n                        JOIN to_cte ON sst.station_cd = to_cte.station_cd\n                    WHERE\n                        sst.pass <> 1\n                ),\n                sst_cte AS (\n                    SELECT\n                        sst.id,\n                        sst.station_cd,\n                        sst.type_cd,\n                        sst.line_group_cd,\n                        sst.pass\n                    FROM\n                        station_station_types AS sst\n                        JOIN sst_cte_c1 ON sst.line_group_cd = sst_cte_c1.line_group_cd\n                        JOIN sst_cte_c2 ON sst.line_group_cd = sst_cte_c2.line_group_cd\n                )\n            SELECT\n            sta.station_cd,\n            sta.station_g_cd,\n            sta.station_name,\n            sta.station_name_k,\n            sta.station_name_r,\n            sta.station_name_rn,\n            sta.station_name_zh,\n            sta.station_name_ko,\n            sta.station_number1,\n            sta.station_number2,\n            sta.station_number3,\n            sta.station_number4,\n            sta.three_letter_code,\n            sta.line_cd,\n            sta.pref_cd,\n            sta.post,\n            sta.address,\n            sta.lon,\n            sta.lat,\n            sta.open_ymd,\n            sta.close_ymd,\n            sta.e_status,\n            sta.e_sort,\n            lin.company_cd,\n            COALESCE(NULLIF(COALESCE(a.line_name, lin.line_name), ''), NULL) AS line_name,\n            COALESCE(NULLIF(COALESCE(a.line_name_k, lin.line_name_k), ''), NULL) AS line_name_k,\n            COALESCE(NULLIF(COALESCE(a.line_name_h, lin.line_name_h), ''), NULL) AS line_name_h,\n            COALESCE(NULLIF(COALESCE(a.line_name_r, lin.line_name_r), ''), NULL) AS line_name_r,\n            COALESCE(NULLIF(COALESCE(a.line_name_zh, lin.line_name_zh), ''), NULL) AS line_name_zh,\n            COALESCE(NULLIF(COALESCE(a.line_name_ko, lin.line_name_ko), ''), NULL) AS line_name_ko,\n            COALESCE(NULLIF(COALESCE(a.line_color_c, lin.line_color_c), ''), NULL) AS line_color_c,\n            lin.line_type,\n            lin.line_symbol1,\n            lin.line_symbol2,\n            lin.line_symbol3,\n            lin.line_symbol4,\n            lin.line_symbol1_color,\n            lin.line_symbol2_color,\n            lin.line_symbol3_color,\n            lin.line_symbol4_color,\n            lin.line_symbol1_shape,\n            lin.line_symbol2_shape,\n            lin.line_symbol3_shape,\n            lin.line_symbol4_shape,\n            COALESCE(lin.average_distance, 0.0)::DOUBLE PRECISION AS average_distance,\n            COALESCE(sst.line_group_cd, NULL)::int AS line_group_cd, -- has_train_types用\n            NULL::int AS type_id,\n            NULL::int AS sst_id,\n            NULL::int AS type_cd,\n            NULL::int AS pass,\n            NULL::text AS type_name,\n            NULL::text AS type_name_k,\n            NULL::text AS type_name_r,\n            NULL::text AS type_name_zh,\n            NULL::text AS type_name_ko,\n            NULL::text AS color,\n            NULL::int AS direction,\n            NULL::int AS kind\n            FROM\n                stations AS sta\n\t\t\t\tJOIN common_lines AS cl ON sta.line_cd = cl.line_cd\n\t\t\t\tJOIN lines AS lin ON lin.line_cd = cl.line_cd\n                LEFT JOIN sst_cte AS sst ON sst.station_cd = sta.station_cd\n                LEFT JOIN types AS tt ON tt.type_cd = sst.type_cd\n                LEFT JOIN line_aliases AS la ON la.station_cd = sta.station_cd\n                LEFT JOIN aliases AS a ON a.id = la.alias_cd\n            WHERE\n                sst.line_group_cd IS NULL\n                AND lin.e_status = 0\n                AND sta.e_status = 0\n                ORDER BY sta.e_sort, sta.station_cd",
+  "query": "WITH\n                from_cte AS (\n                    SELECT\n                        s.station_cd,\n                        s.line_cd\n                    FROM\n                        stations AS s\n                    WHERE\n                        s.station_g_cd = $1\n                ),\n                to_cte AS (\n                    SELECT\n                        s.station_cd,\n                        s.line_cd\n                    FROM\n                        stations AS s\n                    WHERE\n                        s.station_g_cd = $2\n                ),\n                common_lines AS (\n                    SELECT DISTINCT s1.line_cd\n                    FROM stations s1\n                    WHERE s1.station_g_cd = $3\n                        AND s1.e_status = 0\n                        AND ($5::int IS NULL OR s1.line_cd = $5)\n                        AND EXISTS (\n                        SELECT 1\n                        FROM stations s2\n                        WHERE s2.station_g_cd = $4\n                            AND s2.e_status = 0\n                            AND s2.line_cd = s1.line_cd\n                        )\n                ),\n                sst_cte_c1 AS (\n                    SELECT\n                        sst.line_group_cd\n                    FROM\n                        station_station_types AS sst\n                        JOIN from_cte ON sst.station_cd = from_cte.station_cd\n                    WHERE\n                        sst.pass <> 1\n                ),\n                sst_cte_c2 AS (\n                    SELECT\n                        sst.line_group_cd\n                    FROM\n                        station_station_types AS sst\n                        JOIN to_cte ON sst.station_cd = to_cte.station_cd\n                    WHERE\n                        sst.pass <> 1\n                ),\n                sst_cte AS (\n                    SELECT\n                        sst.id,\n                        sst.station_cd,\n                        sst.type_cd,\n                        sst.line_group_cd,\n                        sst.pass\n                    FROM\n                        station_station_types AS sst\n                        JOIN sst_cte_c1 ON sst.line_group_cd = sst_cte_c1.line_group_cd\n                        JOIN sst_cte_c2 ON sst.line_group_cd = sst_cte_c2.line_group_cd\n                )\n            SELECT\n            sta.station_cd,\n            sta.station_g_cd,\n            sta.station_name,\n            sta.station_name_k,\n            sta.station_name_r,\n            sta.station_name_rn,\n            sta.station_name_zh,\n            sta.station_name_ko,\n            sta.station_number1,\n            sta.station_number2,\n            sta.station_number3,\n            sta.station_number4,\n            sta.three_letter_code,\n            sta.line_cd,\n            sta.pref_cd,\n            sta.post,\n            sta.address,\n            sta.lon,\n            sta.lat,\n            sta.open_ymd,\n            sta.close_ymd,\n            sta.e_status,\n            sta.e_sort,\n            lin.company_cd,\n            COALESCE(NULLIF(COALESCE(a.line_name, lin.line_name), ''), NULL) AS line_name,\n            COALESCE(NULLIF(COALESCE(a.line_name_k, lin.line_name_k), ''), NULL) AS line_name_k,\n            COALESCE(NULLIF(COALESCE(a.line_name_h, lin.line_name_h), ''), NULL) AS line_name_h,\n            COALESCE(NULLIF(COALESCE(a.line_name_r, lin.line_name_r), ''), NULL) AS line_name_r,\n            COALESCE(NULLIF(COALESCE(a.line_name_zh, lin.line_name_zh), ''), NULL) AS line_name_zh,\n            COALESCE(NULLIF(COALESCE(a.line_name_ko, lin.line_name_ko), ''), NULL) AS line_name_ko,\n            COALESCE(NULLIF(COALESCE(a.line_color_c, lin.line_color_c), ''), NULL) AS line_color_c,\n            lin.line_type,\n            lin.line_symbol1,\n            lin.line_symbol2,\n            lin.line_symbol3,\n            lin.line_symbol4,\n            lin.line_symbol1_color,\n            lin.line_symbol2_color,\n            lin.line_symbol3_color,\n            lin.line_symbol4_color,\n            lin.line_symbol1_shape,\n            lin.line_symbol2_shape,\n            lin.line_symbol3_shape,\n            lin.line_symbol4_shape,\n            COALESCE(lin.average_distance, 0.0)::DOUBLE PRECISION AS average_distance,\n            COALESCE(sst.line_group_cd, NULL)::int AS line_group_cd, -- has_train_types用\n            NULL::int AS type_id,\n            NULL::int AS sst_id,\n            NULL::int AS type_cd,\n            NULL::int AS pass,\n            NULL::text AS type_name,\n            NULL::text AS type_name_k,\n            NULL::text AS type_name_r,\n            NULL::text AS type_name_zh,\n            NULL::text AS type_name_ko,\n            NULL::text AS color,\n            NULL::int AS direction,\n            NULL::int AS kind\n            FROM\n                stations AS sta\n\t\t\t\tJOIN common_lines AS cl ON sta.line_cd = cl.line_cd\n\t\t\t\tJOIN lines AS lin ON lin.line_cd = cl.line_cd\n                LEFT JOIN sst_cte AS sst ON sst.station_cd = sta.station_cd\n                LEFT JOIN types AS tt ON tt.type_cd = sst.type_cd\n                LEFT JOIN line_aliases AS la ON la.station_cd = sta.station_cd\n                LEFT JOIN aliases AS a ON a.id = la.alias_cd\n            WHERE\n                sst.line_group_cd IS NULL\n                AND lin.e_status = 0\n                AND sta.e_status = 0\n                ORDER BY sta.e_sort, sta.station_cd",
   "describe": {
     "columns": [
       {
@@ -299,6 +299,7 @@
         "Int4",
         "Int4",
         "Int4",
+        "Int4",
         "Int4"
       ]
     },
@@ -363,5 +364,5 @@
       null
     ]
   },
-  "hash": "422bdec51028a86db49d9e2b0babd7f58066d3a2433f5b6416972dfc359540fa"
+  "hash": "64004f2e2ea8f34594c230fe82d5502911473ecef28265350576cd8bee64f7f8"
 }
diff --git a/stationapi/proto b/stationapi/proto
index 9960d525..ca2cd391 160000
--- a/stationapi/proto
+++ b/stationapi/proto
@@ -1 +1 @@
-Subproject commit 9960d5259686991d2bbad39d7f3f9aaf2bbf6485
+Subproject commit ca2cd3914898628f01f714fc2a222390126cdf72
diff --git a/stationapi/src/domain/repository/station_repository.rs b/stationapi/src/domain/repository/station_repository.rs
index aba2b0ae..fdd2b346 100644
--- a/stationapi/src/domain/repository/station_repository.rs
+++ b/stationapi/src/domain/repository/station_repository.rs
@@ -36,6 +36,7 @@ pub trait StationRepository: Send + Sync + 'static {
         &self,
         from_station_id: u32,
         to_station_id: u32,
+        via_line_id: Option<u32>,
     ) -> Result<Vec<Station>, DomainError>;
 }
 
@@ -192,15 +193,28 @@ mod tests {
             &self,
             from_station_id: u32,
             to_station_id: u32,
+            via_line_id: Option<u32>,
         ) -> Result<Vec<Station>, DomainError> {
-            // 簡単なルート検索のモック実装
+            // シンプルなルート検索のモック実装。via_line_id が指定されている場合は
+            // 両駅がその路線に属していることを条件にする。
             let mut result = Vec::new();
 
-            if let Some(from_station) = self.stations.get(&from_station_id) {
+            let from_station = self.stations.get(&from_station_id);
+            let to_station = self.stations.get(&to_station_id);
+
+            if let Some(required_line) = via_line_id {
+                let line_match = |s: &Station| s.line_cd as u32 == required_line;
+                if !from_station.map_or(false, line_match) || !to_station.map_or(false, line_match)
+                {
+                    return Ok(result);
+                }
+            }
+
+            if let Some(from_station) = from_station {
                 result.push(from_station.clone());
             }
 
-            if let Some(to_station) = self.stations.get(&to_station_id) {
+            if let Some(to_station) = to_station {
                 if from_station_id != to_station_id {
                     result.push(to_station.clone());
                 }
@@ -380,7 +394,7 @@ mod tests {
     #[tokio::test]
     async fn test_get_route_stops() {
         let repo = MockStationRepository::new();
-        let result = repo.get_route_stops(1, 2).await.unwrap();
+        let result = repo.get_route_stops(1, 2, None).await.unwrap();
         assert_eq!(result.len(), 2);
         assert_eq!(result[0].station_cd, 1);
         assert_eq!(result[1].station_cd, 2);
@@ -389,7 +403,7 @@ mod tests {
     #[tokio::test]
     async fn test_get_route_stops_same_station() {
         let repo = MockStationRepository::new();
-        let result = repo.get_route_stops(1, 1).await.unwrap();
+        let result = repo.get_route_stops(1, 1, None).await.unwrap();
         assert_eq!(result.len(), 1);
         assert_eq!(result[0].station_cd, 1);
     }
@@ -397,7 +411,25 @@ mod tests {
     #[tokio::test]
     async fn test_get_route_stops_not_found() {
         let repo = MockStationRepository::new();
-        let result = repo.get_route_stops(999, 1000).await.unwrap();
+        let result = repo.get_route_stops(999, 1000, None).await.unwrap();
         assert_eq!(result.len(), 0);
     }
+
+    #[tokio::test]
+    async fn test_get_route_stops_with_via_line_id_match() {
+        let repo = MockStationRepository::new();
+        // 東京駅(1) と 品川駅(4) は line_cd=1001 で一致する
+        let result = repo.get_route_stops(1, 4, Some(1001)).await.unwrap();
+        assert_eq!(result.len(), 2);
+        assert_eq!(result[0].station_cd, 1);
+        assert_eq!(result[1].station_cd, 4);
+    }
+
+    #[tokio::test]
+    async fn test_get_route_stops_with_via_line_id_mismatch() {
+        let repo = MockStationRepository::new();
+        // line_cd が一致しないためルートは返さない
+        let result = repo.get_route_stops(1, 2, Some(1001)).await.unwrap();
+        assert!(result.is_empty());
+    }
 }
diff --git a/stationapi/src/infrastructure/station_repository.rs b/stationapi/src/infrastructure/station_repository.rs
index 28b337e8..257ecccf 100644
--- a/stationapi/src/infrastructure/station_repository.rs
+++ b/stationapi/src/infrastructure/station_repository.rs
@@ -250,9 +250,16 @@ impl StationRepository for MyStationRepository {
         &self,
         from_station_id: u32,
         to_station_id: u32,
+        via_line_id: Option<u32>,
     ) -> Result<Vec<Station>, DomainError> {
         let mut conn = self.pool.acquire().await?;
-        InternalStationRepository::get_route_stops(from_station_id, to_station_id, &mut conn).await
+        InternalStationRepository::get_route_stops(
+            from_station_id,
+            to_station_id,
+            via_line_id,
+            &mut conn,
+        )
+        .await
     }
 }
 
@@ -1169,8 +1176,10 @@ impl InternalStationRepository {
     async fn get_route_stops(
         from_station_id: u32,
         to_station_id: u32,
+        via_line_id: Option<u32>,
         conn: &mut PgConnection,
     ) -> Result<Vec<Station>, DomainError> {
+        let via_line_id = via_line_id.map(|id| id as i32);
         let mut rows = sqlx::query_as!(
             StationRow,
             r#"WITH
@@ -1197,6 +1206,7 @@ impl InternalStationRepository {
                     FROM stations s1
                     WHERE s1.station_g_cd = $3
                         AND s1.e_status = 0
+                        AND ($5::int IS NULL OR s1.line_cd = $5)
                         AND EXISTS (
                         SELECT 1
                         FROM stations s2
@@ -1311,6 +1321,7 @@ impl InternalStationRepository {
             to_station_id as i32,
             from_station_id as i32,
             to_station_id as i32,
+            via_line_id,
         )
         .fetch_all(&mut *conn)
         .await?;
@@ -1436,9 +1447,11 @@ impl InternalStationRepository {
                 LEFT JOIN aliases AS a ON a.id = la.alias_cd
             WHERE
                 sta.e_status = 0
+                AND ($3::int IS NULL OR sta.line_cd = $3)
             ORDER BY sst.id"#,
             from_station_id as i32,
             to_station_id as i32,
+            via_line_id,
         )
         .fetch_all(conn)
         .await?;
diff --git a/stationapi/src/presentation/controller/grpc.rs b/stationapi/src/presentation/controller/grpc.rs
index 2dafd0e5..37938e19 100644
--- a/stationapi/src/presentation/controller/grpc.rs
+++ b/stationapi/src/presentation/controller/grpc.rs
@@ -202,8 +202,13 @@ impl StationApi for MyApi {
     ) -> Result<tonic::Response<RouteResponse>, tonic::Status> {
         let from_id = request.get_ref().from_station_group_id;
         let to_id = request.get_ref().to_station_group_id;
+        let via_line_id = request.get_ref().via_line_id;
 
-        match self.query_use_case.get_routes(from_id, to_id).await {
+        match self
+            .query_use_case
+            .get_routes(from_id, to_id, via_line_id)
+            .await
+        {
             Ok(routes) => {
                 return Ok(Response::new(RouteResponse {
                     routes,
@@ -220,8 +225,13 @@ impl StationApi for MyApi {
     ) -> Result<tonic::Response<RouteMinimalResponse>, tonic::Status> {
         let from_id = request.get_ref().from_station_group_id;
         let to_id = request.get_ref().to_station_group_id;
+        let via_line_id = request.get_ref().via_line_id;
 
-        match self.query_use_case.get_routes_minimal(from_id, to_id).await {
+        match self
+            .query_use_case
+            .get_routes_minimal(from_id, to_id, via_line_id)
+            .await
+        {
             Ok(response) => {
                 return Ok(Response::new(response));
             }
@@ -235,8 +245,13 @@ impl StationApi for MyApi {
     ) -> Result<tonic::Response<RouteTypeResponse>, tonic::Status> {
         let from_id = request.get_ref().from_station_group_id;
         let to_id = request.get_ref().to_station_group_id;
+        let via_line_id = request.get_ref().via_line_id;
 
-        match self.query_use_case.get_train_types(from_id, to_id).await {
+        match self
+            .query_use_case
+            .get_train_types(from_id, to_id, via_line_id)
+            .await
+        {
             Ok(train_types) => {
                 return Ok(Response::new(RouteTypeResponse {
                     train_types: train_types.into_iter().map(|t| t.into()).collect(),
diff --git a/stationapi/src/use_case/interactor/query.rs b/stationapi/src/use_case/interactor/query.rs
index ccf296b6..d2314bcd 100644
--- a/stationapi/src/use_case/interactor/query.rs
+++ b/stationapi/src/use_case/interactor/query.rs
@@ -520,10 +520,11 @@ where
         &self,
         from_station_id: u32,
         to_station_id: u32,
+        via_line_id: Option<u32>,
     ) -> Result<Vec<Route>, UseCaseError> {
         let stops = self
             .station_repository
-            .get_route_stops(from_station_id, to_station_id)
+            .get_route_stops(from_station_id, to_station_id, via_line_id)
             .await?;
 
         let route_row_tree_map = self.build_route_tree_map(&stops);
@@ -620,10 +621,11 @@ where
         &self,
         from_station_id: u32,
         to_station_id: u32,
+        via_line_id: Option<u32>,
     ) -> Result<proto::RouteMinimalResponse, UseCaseError> {
         let stops = self
             .station_repository
-            .get_route_stops(from_station_id, to_station_id)
+            .get_route_stops(from_station_id, to_station_id, via_line_id)
             .await?;
 
         let route_row_tree_map = self.build_route_tree_map(&stops);
@@ -722,10 +724,11 @@ where
         &self,
         from_station_id: u32,
         to_station_id: u32,
+        via_line_id: Option<u32>,
     ) -> Result<Vec<TrainType>, UseCaseError> {
         let stops = self
             .station_repository
-            .get_route_stops(from_station_id, to_station_id)
+            .get_route_stops(from_station_id, to_station_id, via_line_id)
             .await?;
 
         let line_group_id_vec: Vec<u32> = stops
diff --git a/stationapi/src/use_case/traits/query.rs b/stationapi/src/use_case/traits/query.rs
index 9c5a85a6..0aa1abe8 100644
--- a/stationapi/src/use_case/traits/query.rs
+++ b/stationapi/src/use_case/traits/query.rs
@@ -78,16 +78,19 @@ pub trait QueryUseCase: Send + Sync + 'static {
         &self,
         from_station_id: u32,
         to_station_id: u32,
+        via_line_id: Option<u32>,
     ) -> Result<Vec<Route>, UseCaseError>;
     async fn get_routes_minimal(
         &self,
         from_station_id: u32,
         to_station_id: u32,
+        via_line_id: Option<u32>,
     ) -> Result<RouteMinimalResponse, UseCaseError>;
     async fn get_train_types(
         &self,
         from_station_id: u32,
         to_station_id: u32,
+        via_line_id: Option<u32>,
     ) -> Result<Vec<TrainType>, UseCaseError>;
     async fn find_line_by_id(&self, line_id: u32) -> Result<Option<Line>, UseCaseError>;
     async fn get_lines_by_id_vec(&self, line_ids: &[u32]) -> Result<Vec<Line>, UseCaseError>;
