Created
April 10, 2026 17:02
-
-
Save ziadoz/4229bd103064d2eefd06455da3af32a8 to your computer and use it in GitHub Desktop.
PLANNR-7016: SQL queries for finding and fixing duplicate EDI statement numbers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- PLANNR-7016: Duplicate EDI Statement Numbers | |
| -- https://github.com/PlannrCrm/plannr/pull/4593 | |
| -- | |
| -- Both queries below apply to provider_statements and bank_statements. | |
| -- Substitute the table name as needed. | |
| -- ============================================================ | |
| -- 1. Check whether any duplicate (firm_id, number) pairs exist | |
| -- Used in shouldRun() on the unique constraint migrations. | |
| -- Returns 1 if duplicates exist, 0 if not. | |
| -- ============================================================ | |
| SELECT EXISTS( | |
| SELECT 1 | |
| FROM provider_statements | |
| GROUP BY firm_id, number | |
| HAVING COUNT(*) > 1 | |
| ) AS has_duplicates; | |
| -- ============================================================ | |
| -- 2. List all duplicate groups with firm name | |
| -- Useful for auditing before running the fix command. | |
| -- GROUP_CONCAT shows the IDs and created_at of each duplicate | |
| -- in the same order so they can be paired by position. | |
| -- ============================================================ | |
| SELECT | |
| f.name AS firm_name, | |
| ps.firm_id, | |
| ps.number, | |
| COUNT(*) AS count, | |
| GROUP_CONCAT(ps.id ORDER BY ps.created_at SEPARATOR ', ') AS ids, | |
| GROUP_CONCAT(ps.created_at ORDER BY ps.created_at SEPARATOR ', ') AS created_at | |
| FROM provider_statements ps | |
| JOIN firms f ON f.id = ps.firm_id | |
| GROUP BY ps.firm_id, ps.number | |
| HAVING COUNT(*) > 1 | |
| ORDER BY ps.firm_id, ps.number; | |
| -- ============================================================ | |
| -- 3. Fix command: window function query (fix:duplicate-statement-numbers) | |
| -- Inner subquery ranks every row within each (firm_id, number) | |
| -- group (lowest ID = rank 1, kept as-is) and stamps the | |
| -- current max number for the firm onto every row. | |
| -- Outer query filters to rank > 1 (the duplicates) and | |
| -- assigns each a new number by counting up from the firm max. | |
| -- ============================================================ | |
| SELECT | |
| id, | |
| firm_id, | |
| number AS old_number, | |
| new_number | |
| FROM ( | |
| SELECT | |
| id, | |
| firm_id, | |
| number, | |
| max_number + ROW_NUMBER() OVER (PARTITION BY firm_id ORDER BY id) AS new_number, | |
| rank_number | |
| FROM ( | |
| SELECT | |
| id, | |
| firm_id, | |
| number, | |
| ROW_NUMBER() OVER (PARTITION BY firm_id, number ORDER BY id) AS rank_number, | |
| MAX(number) OVER (PARTITION BY firm_id) AS max_number | |
| FROM provider_statements | |
| WHERE firm_id IN ( | |
| -- firms that have at least one duplicate number | |
| SELECT DISTINCT firm_id | |
| FROM provider_statements | |
| GROUP BY firm_id, number | |
| HAVING COUNT(*) > 1 | |
| ) | |
| ) ranked | |
| WHERE rank_number > 1 | |
| ) fixes | |
| ORDER BY firm_id, old_number; | |
| -- ============================================================ | |
| -- 4. Number assignment lock (getLastStatementNumber) | |
| -- Called inside the Eloquent creating observer, wrapped in | |
| -- the existing DB transaction. FOR UPDATE blocks concurrent | |
| -- workers from reading the same max until the insert commits. | |
| -- ============================================================ | |
| SELECT MAX(number) | |
| FROM provider_statements | |
| WHERE firm_id = :firm_id | |
| FOR UPDATE; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment