diff --git a/solution/3600-3699/3657.Find Loyal Customers/README.md b/solution/3600-3699/3657.Find Loyal Customers/README.md index 5dc6309322af3..7c5d9f6060fef 100644 --- a/solution/3600-3699/3657.Find Loyal Customers/README.md +++ b/solution/3600-3699/3657.Find Loyal Customers/README.md @@ -20,7 +20,7 @@ tags:
+------------------+---------+
-| Column Name | Type |
+| Column Name | Type |
+------------------+---------+
| transaction_id | int |
| customer_id | int |
@@ -146,7 +146,46 @@ transaction_type can be either 'purchase' or 'refund'.
#### MySQL
```sql
+# Write your MySQL query statement below
+SELECT customer_id
+FROM customer_transactions
+GROUP BY 1
+HAVING
+ COUNT(1) >= 3
+ AND SUM(transaction_type = 'refund') / COUNT(1) < 0.2
+ AND DATEDIFF(MAX(transaction_date), MIN(transaction_date)) >= 30
+ORDER BY 1;
+```
+#### Pandas
+
+```python
+import pandas as pd
+
+
+def find_loyal_customers(customer_transactions: pd.DataFrame) -> pd.DataFrame:
+ customer_transactions["transaction_date"] = pd.to_datetime(
+ customer_transactions["transaction_date"]
+ )
+ grouped = customer_transactions.groupby("customer_id")
+ agg_df = grouped.agg(
+ total_transactions=("transaction_type", "size"),
+ refund_count=("transaction_type", lambda x: (x == "refund").sum()),
+ min_date=("transaction_date", "min"),
+ max_date=("transaction_date", "max"),
+ ).reset_index()
+ agg_df["date_diff"] = (agg_df["max_date"] - agg_df["min_date"]).dt.days
+ agg_df["refund_ratio"] = agg_df["refund_count"] / agg_df["total_transactions"]
+ result = (
+ agg_df[
+ (agg_df["total_transactions"] >= 3)
+ & (agg_df["refund_ratio"] < 0.2)
+ & (agg_df["date_diff"] >= 30)
+ ][["customer_id"]]
+ .sort_values("customer_id")
+ .reset_index(drop=True)
+ )
+ return result
```
diff --git a/solution/3600-3699/3657.Find Loyal Customers/README_EN.md b/solution/3600-3699/3657.Find Loyal Customers/README_EN.md
index bdec9dcde0275..f9f93ebcd6716 100644
--- a/solution/3600-3699/3657.Find Loyal Customers/README_EN.md
+++ b/solution/3600-3699/3657.Find Loyal Customers/README_EN.md
@@ -20,7 +20,7 @@ tags:
+------------------+---------+
-| Column Name | Type |
+| Column Name | Type |
+------------------+---------+
| transaction_id | int |
| customer_id | int |
@@ -146,7 +146,46 @@ transaction_type can be either 'purchase' or 'refund'.
#### MySQL
```sql
+# Write your MySQL query statement below
+SELECT customer_id
+FROM customer_transactions
+GROUP BY 1
+HAVING
+ COUNT(1) >= 3
+ AND SUM(transaction_type = 'refund') / COUNT(1) < 0.2
+ AND DATEDIFF(MAX(transaction_date), MIN(transaction_date)) >= 30
+ORDER BY 1;
+```
+#### Pandas
+
+```python
+import pandas as pd
+
+
+def find_loyal_customers(customer_transactions: pd.DataFrame) -> pd.DataFrame:
+ customer_transactions["transaction_date"] = pd.to_datetime(
+ customer_transactions["transaction_date"]
+ )
+ grouped = customer_transactions.groupby("customer_id")
+ agg_df = grouped.agg(
+ total_transactions=("transaction_type", "size"),
+ refund_count=("transaction_type", lambda x: (x == "refund").sum()),
+ min_date=("transaction_date", "min"),
+ max_date=("transaction_date", "max"),
+ ).reset_index()
+ agg_df["date_diff"] = (agg_df["max_date"] - agg_df["min_date"]).dt.days
+ agg_df["refund_ratio"] = agg_df["refund_count"] / agg_df["total_transactions"]
+ result = (
+ agg_df[
+ (agg_df["total_transactions"] >= 3)
+ & (agg_df["refund_ratio"] < 0.2)
+ & (agg_df["date_diff"] >= 30)
+ ][["customer_id"]]
+ .sort_values("customer_id")
+ .reset_index(drop=True)
+ )
+ return result
```
diff --git a/solution/3600-3699/3657.Find Loyal Customers/Solution.py b/solution/3600-3699/3657.Find Loyal Customers/Solution.py
new file mode 100644
index 0000000000000..05d8b46f5c0ae
--- /dev/null
+++ b/solution/3600-3699/3657.Find Loyal Customers/Solution.py
@@ -0,0 +1,26 @@
+import pandas as pd
+
+
+def find_loyal_customers(customer_transactions: pd.DataFrame) -> pd.DataFrame:
+ customer_transactions["transaction_date"] = pd.to_datetime(
+ customer_transactions["transaction_date"]
+ )
+ grouped = customer_transactions.groupby("customer_id")
+ agg_df = grouped.agg(
+ total_transactions=("transaction_type", "size"),
+ refund_count=("transaction_type", lambda x: (x == "refund").sum()),
+ min_date=("transaction_date", "min"),
+ max_date=("transaction_date", "max"),
+ ).reset_index()
+ agg_df["date_diff"] = (agg_df["max_date"] - agg_df["min_date"]).dt.days
+ agg_df["refund_ratio"] = agg_df["refund_count"] / agg_df["total_transactions"]
+ result = (
+ agg_df[
+ (agg_df["total_transactions"] >= 3)
+ & (agg_df["refund_ratio"] < 0.2)
+ & (agg_df["date_diff"] >= 30)
+ ][["customer_id"]]
+ .sort_values("customer_id")
+ .reset_index(drop=True)
+ )
+ return result
diff --git a/solution/3600-3699/3657.Find Loyal Customers/Solution.sql b/solution/3600-3699/3657.Find Loyal Customers/Solution.sql
new file mode 100644
index 0000000000000..8e2763b7412a0
--- /dev/null
+++ b/solution/3600-3699/3657.Find Loyal Customers/Solution.sql
@@ -0,0 +1,9 @@
+# Write your MySQL query statement below
+SELECT customer_id
+FROM customer_transactions
+GROUP BY 1
+HAVING
+ COUNT(1) >= 3
+ AND SUM(transaction_type = 'refund') / COUNT(1) < 0.2
+ AND DATEDIFF(MAX(transaction_date), MIN(transaction_date)) >= 30
+ORDER BY 1;