diff --git a/.prettierignore b/.prettierignore
index 05bf32e478051..13715bc116db8 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -25,3 +25,4 @@ node_modules/
/solution/2200-2299/2253.Dynamic Unpivoting of a Table/Solution.sql
/solution/3100-3199/3150.Invalid Tweets II/Solution.sql
/solution/3100-3199/3198.Find Cities in Each State/Solution.sql
+/solution/3300-3399/3328.Find Cities in Each State II/Solution.sql
diff --git a/solution/3300-3399/3328.Find Cities in Each State II/README.md b/solution/3300-3399/3328.Find Cities in Each State II/README.md
new file mode 100644
index 0000000000000..7ff0db455e066
--- /dev/null
+++ b/solution/3300-3399/3328.Find Cities in Each State II/README.md
@@ -0,0 +1,193 @@
+---
+comments: true
+difficulty: 中等
+edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README.md
+tags:
+ - 数据库
+---
+
+
+
+# [3328. Find Cities in Each State II 🔒](https://leetcode.cn/problems/find-cities-in-each-state-ii)
+
+[English Version](/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README_EN.md)
+
+## 题目描述
+
+
+
+
Table: cities
+
+
++-------------+---------+
+| Column Name | Type |
++-------------+---------+
+| state | varchar |
+| city | varchar |
++-------------+---------+
+(state, city) is the combination of columns with unique values for this table.
+Each row of this table contains the state name and the city name within that state.
+
+
+Write a solution to find all the cities in each state and analyze them based on the following requirements:
+
+
+ - Combine all cities into a comma-separated string for each state.
+ - Only include states that have at least
3
cities.
+ - Only include states where at least one city starts with the same letter as the state name.
+
+
+Return the result table ordered by the count of matching-letter cities in descending order and then by state name in ascending order.
+
+The result format is in the following example.
+
+
+Example:
+
+
+
Input:
+
+
cities table:
+
+
++--------------+---------------+
+| state | city |
++--------------+---------------+
+| New York | New York City |
+| New York | Newark |
+| New York | Buffalo |
+| New York | Rochester |
+| California | San Francisco |
+| California | Sacramento |
+| California | San Diego |
+| California | Los Angeles |
+| Texas | Tyler |
+| Texas | Temple |
+| Texas | Taylor |
+| Texas | Dallas |
+| Pennsylvania | Philadelphia |
+| Pennsylvania | Pittsburgh |
+| Pennsylvania | Pottstown |
++--------------+---------------+
+
+
+
Output:
+
+
++-------------+-------------------------------------------+-----------------------+
+| state | cities | matching_letter_count |
++-------------+-------------------------------------------+-----------------------+
+| Pennsylvania| Philadelphia, Pittsburgh, Pottstown | 3 |
+| Texas | Dallas, Taylor, Temple, Tyler | 2 |
+| New York | Buffalo, Newark, New York City, Rochester | 2 |
++-------------+-------------------------------------------+-----------------------+
+
+
+
Explanation:
+
+
+ - Pennsylvania:
+
+
+ - Has 3 cities (meets minimum requirement)
+ - All 3 cities start with 'P' (same as state)
+ - matching_letter_count = 3
+
+
+ - Texas:
+
+ - Has 4 cities (meets minimum requirement)
+ - 2 cities (Temple, Tyler) start with 'T' (same as state)
+ - matching_letter_count = 2
+
+
+ - New York:
+
+ - Has 4 cities (meets minimum requirement)
+ - 2 cities (Newark, New York City) start with 'N' (same as state)
+ - matching_letter_count = 2
+
+
+ - California is not included in the output because:
+
+ - Although it has 4 cities (meets minimum requirement)
+ - No cities start with 'C' (doesn't meet the matching letter requirement)
+
+
+
+
+
+
Note:
+
+
+ - Results are ordered by matching_letter_count in descending order
+ - When matching_letter_count is the same (Texas and New York both have 2), they are ordered by state name alphabetically
+ - Cities in each row are ordered alphabetically
+
+
+
+
+
+## 解法
+
+
+
+### 方法一:分组聚合 + 过滤
+
+我们可以将 `cities` 表按照 `state` 字段进行分组聚合,然后对每个分组进行过滤,筛选出满足条件的分组。
+
+
+
+#### MySQL
+
+```sql
+# Write your MySQL query statement below
+SELECT
+ state,
+ GROUP_CONCAT(city ORDER BY city SEPARATOR ', ') AS cities,
+ COUNT(
+ CASE
+ WHEN LEFT(city, 1) = LEFT(state, 1) THEN 1
+ END
+ ) AS matching_letter_count
+FROM cities
+GROUP BY 1
+HAVING COUNT(city) >= 3 AND matching_letter_count > 0
+ORDER BY 3 DESC, 1;
+```
+
+#### Pandas
+
+```python
+import pandas as pd
+
+
+def state_city_analysis(cities: pd.DataFrame) -> pd.DataFrame:
+ cities["matching_letter"] = cities["city"].str[0] == cities["state"].str[0]
+
+ result = (
+ cities.groupby("state")
+ .agg(
+ cities=("city", lambda x: ", ".join(sorted(x))),
+ matching_letter_count=("matching_letter", "sum"),
+ city_count=("city", "count"),
+ )
+ .reset_index()
+ )
+
+ result = result[(result["city_count"] >= 3) & (result["matching_letter_count"] > 0)]
+
+ result = result.sort_values(
+ by=["matching_letter_count", "state"], ascending=[False, True]
+ )
+
+ result = result.drop(columns=["city_count"])
+
+ return result
+```
+
+
+
+
+
+
diff --git a/solution/3300-3399/3328.Find Cities in Each State II/README_EN.md b/solution/3300-3399/3328.Find Cities in Each State II/README_EN.md
new file mode 100644
index 0000000000000..f1eab9077e28c
--- /dev/null
+++ b/solution/3300-3399/3328.Find Cities in Each State II/README_EN.md
@@ -0,0 +1,193 @@
+---
+comments: true
+difficulty: Medium
+edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README_EN.md
+tags:
+ - Database
+---
+
+
+
+# [3328. Find Cities in Each State II 🔒](https://leetcode.com/problems/find-cities-in-each-state-ii)
+
+[中文文档](/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README.md)
+
+## Description
+
+
+
+Table: cities
+
+
++-------------+---------+
+| Column Name | Type |
++-------------+---------+
+| state | varchar |
+| city | varchar |
++-------------+---------+
+(state, city) is the combination of columns with unique values for this table.
+Each row of this table contains the state name and the city name within that state.
+
+
+Write a solution to find all the cities in each state and analyze them based on the following requirements:
+
+
+ - Combine all cities into a comma-separated string for each state.
+ - Only include states that have at least
3
cities.
+ - Only include states where at least one city starts with the same letter as the state name.
+
+
+Return the result table ordered by the count of matching-letter cities in descending order and then by state name in ascending order.
+
+The result format is in the following example.
+
+
+Example:
+
+
+
Input:
+
+
cities table:
+
+
++--------------+---------------+
+| state | city |
++--------------+---------------+
+| New York | New York City |
+| New York | Newark |
+| New York | Buffalo |
+| New York | Rochester |
+| California | San Francisco |
+| California | Sacramento |
+| California | San Diego |
+| California | Los Angeles |
+| Texas | Tyler |
+| Texas | Temple |
+| Texas | Taylor |
+| Texas | Dallas |
+| Pennsylvania | Philadelphia |
+| Pennsylvania | Pittsburgh |
+| Pennsylvania | Pottstown |
++--------------+---------------+
+
+
+
Output:
+
+
++-------------+-------------------------------------------+-----------------------+
+| state | cities | matching_letter_count |
++-------------+-------------------------------------------+-----------------------+
+| Pennsylvania| Philadelphia, Pittsburgh, Pottstown | 3 |
+| Texas | Dallas, Taylor, Temple, Tyler | 2 |
+| New York | Buffalo, Newark, New York City, Rochester | 2 |
++-------------+-------------------------------------------+-----------------------+
+
+
+
Explanation:
+
+
+ - Pennsylvania:
+
+
+ - Has 3 cities (meets minimum requirement)
+ - All 3 cities start with 'P' (same as state)
+ - matching_letter_count = 3
+
+
+ - Texas:
+
+ - Has 4 cities (meets minimum requirement)
+ - 2 cities (Temple, Tyler) start with 'T' (same as state)
+ - matching_letter_count = 2
+
+
+ - New York:
+
+ - Has 4 cities (meets minimum requirement)
+ - 2 cities (Newark, New York City) start with 'N' (same as state)
+ - matching_letter_count = 2
+
+
+ - California is not included in the output because:
+
+ - Although it has 4 cities (meets minimum requirement)
+ - No cities start with 'C' (doesn't meet the matching letter requirement)
+
+
+
+
+
+
Note:
+
+
+ - Results are ordered by matching_letter_count in descending order
+ - When matching_letter_count is the same (Texas and New York both have 2), they are ordered by state name alphabetically
+ - Cities in each row are ordered alphabetically
+
+
+
+
+
+## Solutions
+
+
+
+### Solution 1: Group Aggregation + Filtering
+
+We can group the `cities` table by the `state` field, then apply filtering on each group to retain only the groups that meet the specified conditions.
+
+
+
+#### MySQL
+
+```sql
+# Write your MySQL query statement below
+SELECT
+ state,
+ GROUP_CONCAT(city ORDER BY city SEPARATOR ', ') AS cities,
+ COUNT(
+ CASE
+ WHEN LEFT(city, 1) = LEFT(state, 1) THEN 1
+ END
+ ) AS matching_letter_count
+FROM cities
+GROUP BY 1
+HAVING COUNT(city) >= 3 AND matching_letter_count > 0
+ORDER BY 3 DESC, 1;
+```
+
+#### Pandas
+
+```python
+import pandas as pd
+
+
+def state_city_analysis(cities: pd.DataFrame) -> pd.DataFrame:
+ cities["matching_letter"] = cities["city"].str[0] == cities["state"].str[0]
+
+ result = (
+ cities.groupby("state")
+ .agg(
+ cities=("city", lambda x: ", ".join(sorted(x))),
+ matching_letter_count=("matching_letter", "sum"),
+ city_count=("city", "count"),
+ )
+ .reset_index()
+ )
+
+ result = result[(result["city_count"] >= 3) & (result["matching_letter_count"] > 0)]
+
+ result = result.sort_values(
+ by=["matching_letter_count", "state"], ascending=[False, True]
+ )
+
+ result = result.drop(columns=["city_count"])
+
+ return result
+```
+
+
+
+
+
+
diff --git a/solution/3300-3399/3328.Find Cities in Each State II/Solution.py b/solution/3300-3399/3328.Find Cities in Each State II/Solution.py
new file mode 100644
index 0000000000000..3c33145d67547
--- /dev/null
+++ b/solution/3300-3399/3328.Find Cities in Each State II/Solution.py
@@ -0,0 +1,25 @@
+import pandas as pd
+
+
+def state_city_analysis(cities: pd.DataFrame) -> pd.DataFrame:
+ cities["matching_letter"] = cities["city"].str[0] == cities["state"].str[0]
+
+ result = (
+ cities.groupby("state")
+ .agg(
+ cities=("city", lambda x: ", ".join(sorted(x))),
+ matching_letter_count=("matching_letter", "sum"),
+ city_count=("city", "count"),
+ )
+ .reset_index()
+ )
+
+ result = result[(result["city_count"] >= 3) & (result["matching_letter_count"] > 0)]
+
+ result = result.sort_values(
+ by=["matching_letter_count", "state"], ascending=[False, True]
+ )
+
+ result = result.drop(columns=["city_count"])
+
+ return result
diff --git a/solution/3300-3399/3328.Find Cities in Each State II/Solution.sql b/solution/3300-3399/3328.Find Cities in Each State II/Solution.sql
new file mode 100644
index 0000000000000..ce985e262d394
--- /dev/null
+++ b/solution/3300-3399/3328.Find Cities in Each State II/Solution.sql
@@ -0,0 +1,13 @@
+# Write your MySQL query statement below
+SELECT
+ state,
+ GROUP_CONCAT(city ORDER BY city SEPARATOR ', ') AS cities,
+ COUNT(
+ CASE
+ WHEN LEFT(city, 1) = LEFT(state, 1) THEN 1
+ END
+ ) AS matching_letter_count
+FROM cities
+GROUP BY 1
+HAVING COUNT(city) >= 3 AND matching_letter_count > 0
+ORDER BY 3 DESC, 1;
diff --git a/solution/DATABASE_README.md b/solution/DATABASE_README.md
index c396c38a3b2ad..c90cbda654bbf 100644
--- a/solution/DATABASE_README.md
+++ b/solution/DATABASE_README.md
@@ -298,6 +298,7 @@
| 3293 | [计算产品最终价格](/solution/3200-3299/3293.Calculate%20Product%20Final%20Price/README.md) | `数据库` | 中等 | 🔒 |
| 3308 | [Find Top Performing Driver](/solution/3300-3399/3308.Find%20Top%20Performing%20Driver/README.md) | `数据库` | 中等 | 🔒 |
| 3322 | [英超积分榜排名 III](/solution/3300-3399/3322.Premier%20League%20Table%20Ranking%20III/README.md) | `数据库` | 中等 | 🔒 |
+| 3328 | [Find Cities in Each State II](/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README.md) | | 中等 | 🔒 |
## 版权
diff --git a/solution/DATABASE_README_EN.md b/solution/DATABASE_README_EN.md
index 0ad562b350bea..46112987e16f6 100644
--- a/solution/DATABASE_README_EN.md
+++ b/solution/DATABASE_README_EN.md
@@ -296,6 +296,7 @@ Press Control + F(or Command + F on
| 3293 | [Calculate Product Final Price](/solution/3200-3299/3293.Calculate%20Product%20Final%20Price/README_EN.md) | `Database` | Medium | 🔒 |
| 3308 | [Find Top Performing Driver](/solution/3300-3399/3308.Find%20Top%20Performing%20Driver/README_EN.md) | `Database` | Medium | 🔒 |
| 3322 | [Premier League Table Ranking III](/solution/3300-3399/3322.Premier%20League%20Table%20Ranking%20III/README_EN.md) | `Database` | Medium | 🔒 |
+| 3328 | [Find Cities in Each State II](/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README_EN.md) | | Medium | 🔒 |
## Copyright
diff --git a/solution/README.md b/solution/README.md
index fff63e2896af9..46544026be341 100644
--- a/solution/README.md
+++ b/solution/README.md
@@ -3338,6 +3338,7 @@
| 3325 | [字符至少出现 K 次的子字符串 I](/solution/3300-3399/3325.Count%20Substrings%20With%20K-Frequency%20Characters%20I/README.md) | | 中等 | 第 420 场周赛 |
| 3326 | [使数组非递减的最少除法操作次数](/solution/3300-3399/3326.Minimum%20Division%20Operations%20to%20Make%20Array%20Non%20Decreasing/README.md) | | 中等 | 第 420 场周赛 |
| 3327 | [判断 DFS 字符串是否是回文串](/solution/3300-3399/3327.Check%20if%20DFS%20Strings%20Are%20Palindromes/README.md) | | 困难 | 第 420 场周赛 |
+| 3328 | [Find Cities in Each State II](/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README.md) | | 中等 | 🔒 |
## 版权
diff --git a/solution/README_EN.md b/solution/README_EN.md
index b07d1b10a7ede..cbe04361f3fea 100644
--- a/solution/README_EN.md
+++ b/solution/README_EN.md
@@ -3336,6 +3336,7 @@ Press Control + F(or Command + F on
| 3325 | [Count Substrings With K-Frequency Characters I](/solution/3300-3399/3325.Count%20Substrings%20With%20K-Frequency%20Characters%20I/README_EN.md) | | Medium | Weekly Contest 420 |
| 3326 | [Minimum Division Operations to Make Array Non Decreasing](/solution/3300-3399/3326.Minimum%20Division%20Operations%20to%20Make%20Array%20Non%20Decreasing/README_EN.md) | | Medium | Weekly Contest 420 |
| 3327 | [Check if DFS Strings Are Palindromes](/solution/3300-3399/3327.Check%20if%20DFS%20Strings%20Are%20Palindromes/README_EN.md) | | Hard | Weekly Contest 420 |
+| 3328 | [Find Cities in Each State II](/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README_EN.md) | | Medium | 🔒 |
## Copyright