条件时间转状态计算:销售代表达标状态时长测算需求
Alright, let's tackle this problem head-on. You want to calculate how long it takes a sales rep to hit specific statuses—each tied to accumulating a certain number of users with non-null date_applied—measured from their hire date (date_created). Plus, you need to integrate this with non-aggregated CASE WHEN logic for status tracking. Here's a practical, step-by-step solution:
The key steps are:
- First, rank each rep's valid clients (those with non-null
date_applied) by their application date to identify when the rep hits each threshold. - Calculate the time difference between the rep's hire date and the date they reached each status threshold.
- Use non-aggregated checks to determine the rep's current highest status without breaking your query structure.
Let's assume you have two tables:
sales_reps: Contains rep IDs and their hire dates (rep_id,date_created)users: Links users to reps, with application dates (user_id,rep_id,date_applied)
1. Rank Valid Clients per Rep
Use a window function to assign a sequential rank to each valid client for a rep, ordered by their application date. This lets us pinpoint exactly when the rep hits each x-client threshold:
WITH ranked_valid_clients AS ( SELECT rep_id, date_applied, -- Assign rank: 1 = first valid client, 5 = fifth, etc. ROW_NUMBER() OVER ( PARTITION BY rep_id ORDER BY date_applied ASC ) AS client_rank FROM users WHERE date_applied IS NOT NULL -- Only count users who applied )
2. Calculate Time to Reach Each Status
Join this ranked data with the sales_reps table to compute the time between hire date and hitting each threshold. We'll use MAX(CASE...) to grab the exact date the rep hit each x-client mark, then calculate the duration:
WITH ranked_valid_clients AS ( SELECT rep_id, date_applied, ROW_NUMBER() OVER (PARTITION BY rep_id ORDER BY date_applied ASC) AS client_rank FROM users WHERE date_applied IS NOT NULL ) SELECT sr.rep_id, sr.date_created AS hire_date, -- Time to reach Status A (5 clients example) DATEDIFF(day, sr.date_created, MAX(CASE WHEN rvc.client_rank = 5 THEN rvc.date_applied END)) AS days_to_status_a, -- Time to reach Status B (10 clients example) DATEDIFF(day, sr.date_created, MAX(CASE WHEN rvc.client_rank = 10 THEN rvc.date_applied END)) AS days_to_status_b, -- Non-aggregated status check (current highest status) CASE WHEN EXISTS ( SELECT 1 FROM ranked_valid_clients rvc2 WHERE rvc2.rep_id = sr.rep_id AND rvc2.client_rank >= 10 ) THEN 'Status B' WHEN EXISTS ( SELECT 1 FROM ranked_valid_clients rvc2 WHERE rvc2.rep_id = sr.rep_id AND rvc2.client_rank >= 5 ) THEN 'Status A' ELSE 'Not Qualified' END AS current_status FROM sales_reps sr LEFT JOIN ranked_valid_clients rvc ON sr.rep_id = rvc.rep_id GROUP BY sr.rep_id, sr.date_created;
Key Notes
- Database-Specific Adjustments: Date functions vary by SQL dialect. For example:
- PostgreSQL: Use
AGE(rvc.date_applied, sr.date_created)instead ofDATEDIFF - SQL Server:
DATEDIFF(day, sr.date_created, ...)works as shown - MySQL:
DATEDIFF(rvc.date_applied, sr.date_created)(order reversed)
- PostgreSQL: Use
- Handling Unmet Thresholds: If a rep hasn't hit a threshold,
MAX(...)returnsNULL. UseCOALESCEto replace this with a default (e.g.,COALESCE(DATEDIFF(...), -1)to mark unmet statuses) - Non-Aggregated Status Logic: The
EXISTSchecks let you determine the rep's current status without relying on aggregated fields, which keeps your query flexible for non-aggregated use cases.
内容的提问来源于stack exchange,提问作者user8834780

