322 lines
18 KiB
SQL
322 lines
18 KiB
SQL
-- ============================================================================
|
||||
|
|
-- پیشبررسی مهاجرت — فقط شمارش، صفر داده
|
|||
|
|
-- ============================================================================
|
|||
|
|
--
|
|||
|
|
-- روی دیتابیس MySQL قدیمی (اسکیمای `oapi`) اجرا شود.
|
|||
|
|
--
|
|||
|
|
-- ⚠️ این فایل فقط SELECT COUNT / SUM / MIN / MAX دارد.
|
|||
|
|
-- هیچ INSERT / UPDATE / DELETE / DROP / ALTER در آن نیست.
|
|||
|
|
-- هیچ ستون متنی (نام، موبایل، کد ملی، آدرس) در خروجی ظاهر نمیشود.
|
|||
|
|
--
|
|||
|
|
-- اجرا:
|
|||
|
|
-- mysql -u USER -p -h HOST -P 3305 oapi < migration-precheck.sql > out.txt
|
|||
|
|
--
|
|||
|
|
-- سپس محتوای out.txt کپی شود. خروجی فقط عدد است.
|
|||
|
|
--
|
|||
|
|
-- مرجع: docs/DATA-MIGRATION-MAP.md §۳ · §۵.۳ · §۵.۵ · §۵.۶
|
|||
|
|
-- ============================================================================
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- بخش ۱ — حجم کار: تعداد ردیف زنده و حذفشدهی نرم
|
|||
|
|
-- مرجع: §۵.۶ — ردیف حذفشده نباید منتقل شود
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
SELECT '=== 1. ROW COUNTS ===' AS section;
|
|||
|
|
|
|||
|
|
SELECT 'customers' AS tbl, COUNT(*) AS live, SUM(deleted_at IS NOT NULL) AS soft_deleted FROM customers
|
|||
|
|
UNION ALL SELECT 'users', COUNT(*), SUM(deleted_at IS NOT NULL) FROM users
|
|||
|
|
UNION ALL SELECT 'orders', COUNT(*), SUM(deleted_at IS NOT NULL) FROM orders
|
|||
|
|
UNION ALL SELECT 'order_items', COUNT(*), SUM(deleted_at IS NOT NULL) FROM order_items
|
|||
|
|
UNION ALL SELECT 'cashes', COUNT(*), SUM(deleted_at IS NOT NULL) FROM cashes
|
|||
|
|
UNION ALL SELECT 'product', COUNT(*), SUM(deleted_at IS NOT NULL) FROM product
|
|||
|
|
UNION ALL SELECT 'variant', COUNT(*), SUM(deleted_at IS NOT NULL) FROM products_productvarient
|
|||
|
|
UNION ALL SELECT 'prod_image', COUNT(*), SUM(deleted_at IS NOT NULL) FROM products_productimage
|
|||
|
|
UNION ALL SELECT 'category', COUNT(*), SUM(deleted_at IS NOT NULL) FROM category_collection
|
|||
|
|
UNION ALL SELECT 'image', COUNT(*), SUM(deleted_at IS NOT NULL) FROM image
|
|||
|
|
UNION ALL SELECT 'cities', COUNT(*), SUM(deleted_at IS NOT NULL) FROM cities
|
|||
|
|
UNION ALL SELECT 'branches', COUNT(*), SUM(deleted_at IS NOT NULL) FROM branches
|
|||
|
|
UNION ALL SELECT 'workshops', COUNT(*), SUM(deleted_at IS NOT NULL) FROM workshops
|
|||
|
|
UNION ALL SELECT 'custom_orders', COUNT(*), SUM(deleted_at IS NOT NULL) FROM custom_orders
|
|||
|
|
UNION ALL SELECT 'comments', COUNT(*), SUM(deleted_at IS NOT NULL) FROM comments
|
|||
|
|
UNION ALL SELECT 'messages', COUNT(*), 0 FROM messages
|
|||
|
|
UNION ALL SELECT 'notify', COUNT(*), SUM(deleted_at IS NOT NULL) FROM notify
|
|||
|
|
UNION ALL SELECT 'fav', COUNT(*), 0 FROM fav
|
|||
|
|
UNION ALL SELECT 'permission', COUNT(*), 0 FROM permission
|
|||
|
|
UNION ALL SELECT 'config_statics', COUNT(*), SUM(deleted_at IS NOT NULL) FROM config_statics;
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- بخش ۲ — 🔴 یکتایی: آیا @unique در Prisma میشکند؟
|
|||
|
|
-- مرجع: §۳ — مبدأ هیچ unique index ندارد
|
|||
|
|
-- هر عدد غیرصفر یعنی مهاجرت در میانه متوقف میشود
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
SELECT '=== 2. UNIQUENESS (any nonzero = migration breaks) ===' AS section;
|
|||
|
|
|
|||
|
|
-- چند *گروه* موبایل تکراری، و چند ردیف درگیرند
|
|||
|
|
SELECT 'dup_mobile_groups' AS metric, COUNT(*) AS n FROM (
|
|||
|
|
SELECT mobile FROM customers
|
|||
|
|
WHERE deleted_at IS NULL AND mobile IS NOT NULL AND mobile <> ''
|
|||
|
|
GROUP BY mobile HAVING COUNT(*) > 1
|
|||
|
|
) d
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'dup_mobile_rows', COALESCE(SUM(c),0) FROM (
|
|||
|
|
SELECT COUNT(*) AS c FROM customers
|
|||
|
|
WHERE deleted_at IS NULL AND mobile IS NOT NULL AND mobile <> ''
|
|||
|
|
GROUP BY mobile HAVING COUNT(*) > 1
|
|||
|
|
) d2
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'dup_ncode_groups', COUNT(*) FROM (
|
|||
|
|
SELECT ncode FROM customers
|
|||
|
|
WHERE deleted_at IS NULL AND ncode IS NOT NULL AND ncode <> ''
|
|||
|
|
GROUP BY ncode HAVING COUNT(*) > 1
|
|||
|
|
) d3
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'dup_ncode_rows', COALESCE(SUM(c),0) FROM (
|
|||
|
|
SELECT COUNT(*) AS c FROM customers
|
|||
|
|
WHERE deleted_at IS NULL AND ncode IS NOT NULL AND ncode <> ''
|
|||
|
|
GROUP BY ncode HAVING COUNT(*) > 1
|
|||
|
|
) d4;
|
|||
|
|
|
|||
|
|
-- تهیبودن: Prisma هر دو را NOT NULL میخواهد
|
|||
|
|
SELECT 'empty_mobile' AS metric, SUM(mobile IS NULL OR mobile = '') AS n FROM customers WHERE deleted_at IS NULL
|
|||
|
|
UNION ALL SELECT 'empty_ncode', SUM(ncode IS NULL OR ncode = '') FROM customers WHERE deleted_at IS NULL;
|
|||
|
|
|
|||
|
|
-- تداخل شماره بین مشتری و کاربر ادمین (D21: «کارشناس برنده است»)
|
|||
|
|
SELECT 'mobile_collision_customer_vs_user' AS metric, COUNT(*) AS n
|
|||
|
|
FROM customers c JOIN users u ON u.mobile = c.mobile
|
|||
|
|
WHERE c.deleted_at IS NULL AND u.deleted_at IS NULL
|
|||
|
|
AND c.mobile IS NOT NULL AND c.mobile <> '';
|
|||
|
|
|
|||
|
|
-- یکتایی در جدول users هم بررسی شود
|
|||
|
|
SELECT 'dup_user_mobile_groups' AS metric, COUNT(*) AS n FROM (
|
|||
|
|
SELECT mobile FROM users
|
|||
|
|
WHERE deleted_at IS NULL AND mobile IS NOT NULL AND mobile <> ''
|
|||
|
|
GROUP BY mobile HAVING COUNT(*) > 1
|
|||
|
|
) d;
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- بخش ۳ — 🔴 نام: آیا D0 درست است؟
|
|||
|
|
-- مرجع: §۲ — fname/lname از قبل وجود دارند
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
SELECT '=== 3. NAME PARTS (does `name` agree with fname+lname?) ===' AS section;
|
|||
|
|
|
|||
|
|
SELECT
|
|||
|
|
SUM(fname IS NULL OR fname = '') AS empty_fname,
|
|||
|
|
SUM(lname IS NULL OR lname = '') AS empty_lname,
|
|||
|
|
SUM(name IS NULL OR name = '') AS empty_name,
|
|||
|
|
-- ردیفهایی که name با اجزا نمیخواند → trigger مقصد name را بازنویسی میکند
|
|||
|
|
SUM(TRIM(COALESCE(name,'')) <> TRIM(CONCAT(COALESCE(fname,''),' ',COALESCE(lname,'')))) AS name_mismatch,
|
|||
|
|
-- اجزا تهی ولی name پر → تنها حالتی که تجزیه لازم است
|
|||
|
|
SUM((fname IS NULL OR fname = '') AND (lname IS NULL OR lname = '')
|
|||
|
|
AND name IS NOT NULL AND name <> '') AS parts_empty_name_set
|
|||
|
|
FROM customers WHERE deleted_at IS NULL;
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- بخش ۴ — enum ها: آیا مقداری بینگاشت میماند؟
|
|||
|
|
-- مرجع: §۵.۳ (type) · §۵.۵ (verify) · §۷.۳ (sts)
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
SELECT '=== 4. ENUMS ===' AS section;
|
|||
|
|
|
|||
|
|
-- type: 1..5 نگاشت دارند. NULL یا خارج از بازه → بیصدا APP_SHOPKEEPER میشود
|
|||
|
|
SELECT 'customers.type' AS col, CAST(type AS CHAR) AS val, COUNT(*) AS n
|
|||
|
|
FROM customers WHERE deleted_at IS NULL GROUP BY type ORDER BY type;
|
|||
|
|
|
|||
|
|
-- sts و active: دو سوییچ مجزا
|
|||
|
|
SELECT 'customers.sts' AS col, CAST(sts AS CHAR) AS val, COUNT(*) AS n
|
|||
|
|
FROM customers WHERE deleted_at IS NULL GROUP BY sts
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'customers.active', CAST(active AS CHAR), COUNT(*)
|
|||
|
|
FROM customers WHERE deleted_at IS NULL GROUP BY active
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'customers.is_archive', CAST(is_archive AS CHAR), COUNT(*)
|
|||
|
|
FROM customers WHERE deleted_at IS NULL GROUP BY is_archive;
|
|||
|
|
|
|||
|
|
-- دو ستون تأیید → یک enum چهارحالته. حالت (0,1) در مقصد نماینده ندارد
|
|||
|
|
SELECT 'verify_step_combo' AS col,
|
|||
|
|
CONCAT(COALESCE(CAST(sts_verify_step_one AS CHAR),'NULL'), ',',
|
|||
|
|
COALESCE(CAST(sts_verify_step_two AS CHAR),'NULL')) AS val,
|
|||
|
|
COUNT(*) AS n
|
|||
|
|
FROM customers WHERE deleted_at IS NULL
|
|||
|
|
GROUP BY sts_verify_step_one, sts_verify_step_two;
|
|||
|
|
|
|||
|
|
-- وضعیت سفارش عمده: 0..6 نگاشت دارند
|
|||
|
|
SELECT 'orders.sts' AS col, CAST(sts AS CHAR) AS val, COUNT(*) AS n
|
|||
|
|
FROM orders WHERE deleted_at IS NULL GROUP BY sts ORDER BY sts;
|
|||
|
|
|
|||
|
|
-- اسناد مالی: type → LedgerSourceType (9,1,2,3,4)، confirmed حیاتی است (D24)
|
|||
|
|
SELECT 'cashes.type' AS col, CAST(type AS CHAR) AS val, COUNT(*) AS n
|
|||
|
|
FROM cashes WHERE deleted_at IS NULL GROUP BY type ORDER BY type;
|
|||
|
|
|
|||
|
|
SELECT 'cashes.confirmed' AS col, CAST(confirmed AS CHAR) AS val, COUNT(*) AS n
|
|||
|
|
FROM cashes WHERE deleted_at IS NULL GROUP BY confirmed;
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- بخش ۵ — 🔴 پول و وزن: مبنای تطبیق + تأیید اینکه آستانه لازم است
|
|||
|
|
-- مرجع: §۴ — ۱۱۰ ستون double، «صفر اختلاف» دستنیافتنی است
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
SELECT '=== 5. MONEY / WEIGHT TOTALS (migration must match these) ===' AS section;
|
|||
|
|
|
|||
|
|
SELECT
|
|||
|
|
COUNT(*) AS n_customers,
|
|||
|
|
CAST(SUM(remain) AS CHAR) AS sum_gold_debt,
|
|||
|
|
CAST(SUM(rial_remain) AS CHAR) AS sum_rial_debt,
|
|||
|
|
CAST(SUM(gram_level) AS CHAR) AS sum_credit_limit,
|
|||
|
|
SUM(remain <> 0) AS n_nonzero_gold,
|
|||
|
|
SUM(rial_remain <> 0) AS n_nonzero_rial,
|
|||
|
|
SUM(remain < 0) AS n_negative_gold,
|
|||
|
|
SUM(rial_remain < 0) AS n_negative_rial
|
|||
|
|
FROM customers WHERE deleted_at IS NULL;
|
|||
|
|
|
|||
|
|
-- 🔴 شاهدِ مشکل double: چند ردیف مقداری دارند که در Decimal(14,4) جا نمیشود؟
|
|||
|
|
-- عدد غیرصفر = گِردکردن رخ میدهد = «صفر اختلاف» ناممکن است
|
|||
|
|
SELECT 'gold_needs_rounding' AS metric, SUM(remain <> ROUND(remain, 4)) AS n
|
|||
|
|
FROM customers WHERE deleted_at IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'credit_needs_rounding', SUM(gram_level <> ROUND(gram_level, 4))
|
|||
|
|
FROM customers WHERE deleted_at IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'order_weight_needs_rounding', SUM(w <> ROUND(w, 4))
|
|||
|
|
FROM orders WHERE deleted_at IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'cash_amount_needs_rounding', SUM(remain <> ROUND(remain, 4))
|
|||
|
|
FROM cashes WHERE deleted_at IS NULL;
|
|||
|
|
|
|||
|
|
-- فقط اسناد تأییدشده در موجودی حساب میشوند (D24)
|
|||
|
|
SELECT 'confirmed_only' AS scope,
|
|||
|
|
CAST(SUM(remain) AS CHAR) AS sum_gold,
|
|||
|
|
CAST(SUM(rial_remain) AS CHAR) AS sum_rial,
|
|||
|
|
COUNT(*) AS n
|
|||
|
|
FROM cashes WHERE deleted_at IS NULL AND confirmed = 1;
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- بخش ۶ — یکپارچگی ارجاعی (مبدأ صفر FK دارد — §۱۱)
|
|||
|
|
-- ارجاع یتیم = ردیفی که مهاجرت نمیتواند وصل کند
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
SELECT '=== 6. ORPHAN REFERENCES (no FKs exist in source) ===' AS section;
|
|||
|
|
|
|||
|
|
SELECT 'customer.city_id -> cities' AS ref, COUNT(*) AS orphans
|
|||
|
|
FROM customers c LEFT JOIN cities ci ON ci.id = c.city_id
|
|||
|
|
WHERE c.deleted_at IS NULL AND c.city_id IS NOT NULL AND ci.id IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'customer.reagent_id -> users', COUNT(*)
|
|||
|
|
FROM customers c LEFT JOIN users u ON u.id = c.reagent_id
|
|||
|
|
WHERE c.deleted_at IS NULL AND c.reagent_id IS NOT NULL AND u.id IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'customer.image_id -> image', COUNT(*)
|
|||
|
|
FROM customers c LEFT JOIN image i ON i.id = c.image_id
|
|||
|
|
WHERE c.deleted_at IS NULL AND c.image_id IS NOT NULL AND i.id IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'order.customer_id -> customers', COUNT(*)
|
|||
|
|
FROM orders o LEFT JOIN customers c ON c.id = o.customer_id
|
|||
|
|
WHERE o.deleted_at IS NULL AND o.customer_id IS NOT NULL AND c.id IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'order_items.order_id -> orders', COUNT(*)
|
|||
|
|
FROM order_items oi LEFT JOIN orders o ON o.id = oi.order_id
|
|||
|
|
WHERE oi.deleted_at IS NULL AND oi.order_id IS NOT NULL AND o.id IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'order_items.variant_id -> variant', COUNT(*)
|
|||
|
|
FROM order_items oi LEFT JOIN products_productvarient v ON v.id = oi.variant_id
|
|||
|
|
WHERE oi.deleted_at IS NULL AND oi.variant_id IS NOT NULL AND v.id IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'cashes.customer_id -> customers', COUNT(*)
|
|||
|
|
FROM cashes ca LEFT JOIN customers c ON c.id = ca.customer_id
|
|||
|
|
WHERE ca.deleted_at IS NULL AND ca.customer_id IS NOT NULL AND c.id IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'variant.product_id_id -> product', COUNT(*)
|
|||
|
|
FROM products_productvarient v LEFT JOIN product p ON p.id = v.product_id_id
|
|||
|
|
WHERE v.deleted_at IS NULL AND v.product_id_id IS NOT NULL AND p.id IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'fav.customer_id -> customers', COUNT(*)
|
|||
|
|
FROM fav f LEFT JOIN customers c ON c.id = f.customer_id
|
|||
|
|
WHERE c.id IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'fav.product_id -> product', COUNT(*)
|
|||
|
|
FROM fav f LEFT JOIN product p ON p.id = f.product_id
|
|||
|
|
WHERE p.id IS NULL;
|
|||
|
|
|
|||
|
|
-- 🔴 fav هیچ PK ندارد → ردیف تکراری ممکن است (§۱۰)
|
|||
|
|
SELECT 'fav_duplicate_pairs' AS metric, COUNT(*) AS n FROM (
|
|||
|
|
SELECT customer_id, product_id FROM fav
|
|||
|
|
GROUP BY customer_id, product_id HAVING COUNT(*) > 1
|
|||
|
|
) d;
|
|||
|
|
|
|||
|
|
-- permission هم PK ندارد
|
|||
|
|
SELECT 'permission_duplicate_rows' AS metric, COUNT(*) AS n FROM (
|
|||
|
|
SELECT rid, ut FROM permission GROUP BY rid, ut HAVING COUNT(*) > 1
|
|||
|
|
) d;
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- بخش ۷ — ستونهای مبهم: نوع واقعی داده
|
|||
|
|
-- مرجع: §۸ — ayar متنی یا عددی؟ تاریخ جلالی یا میلادی؟
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
SELECT '=== 7. AMBIGUOUS COLUMNS ===' AS section;
|
|||
|
|
|
|||
|
|
-- ayar در مبدأ varchar(20) است ولی مقصد Int? — مقدار غیرعددی میشکند
|
|||
|
|
SELECT 'ayar_total' AS metric, COUNT(*) AS n FROM cashes WHERE deleted_at IS NULL AND ayar IS NOT NULL AND ayar <> ''
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'ayar_non_numeric', COUNT(*) FROM cashes
|
|||
|
|
WHERE deleted_at IS NULL AND ayar IS NOT NULL AND ayar <> '' AND ayar NOT REGEXP '^[0-9]+$';
|
|||
|
|
|
|||
|
|
-- recive_date / proceed_at در مبدأ varchar هستند — جلالی یا میلادی؟
|
|||
|
|
-- طول رشته و اینکه با 13 یا 14 شروع میشود، نوع تقویم را لو میدهد
|
|||
|
|
SELECT 'recive_date_set' AS metric, COUNT(*) AS n FROM cashes WHERE deleted_at IS NULL AND recive_date IS NOT NULL AND recive_date <> ''
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'recive_date_starts_13x', COUNT(*) FROM cashes WHERE deleted_at IS NULL AND recive_date LIKE '13%'
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'recive_date_starts_14x', COUNT(*) FROM cashes WHERE deleted_at IS NULL AND recive_date LIKE '14%'
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'recive_date_starts_20x', COUNT(*) FROM cashes WHERE deleted_at IS NULL AND recive_date LIKE '20%'
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'proceed_at_set', COUNT(*) FROM cashes WHERE deleted_at IS NULL AND proceed_at IS NOT NULL AND proceed_at <> '';
|
|||
|
|
|
|||
|
|
-- ستونهای دادهی غیرقابلبازسازی (§۵.۲ گروه ج) — چند ردیف واقعاً مقدار دارند؟
|
|||
|
|
SELECT 'has_birth_date' AS metric, COUNT(*) AS n FROM customers WHERE deleted_at IS NULL AND birth_date IS NOT NULL
|
|||
|
|
UNION ALL SELECT 'has_marriage_date', COUNT(*) FROM customers WHERE deleted_at IS NULL AND marriage_date IS NOT NULL
|
|||
|
|
UNION ALL SELECT 'has_token_mobile', COUNT(*) FROM customers WHERE deleted_at IS NULL AND token_mobile IS NOT NULL AND token_mobile <> ''
|
|||
|
|
UNION ALL SELECT 'has_new_city', COUNT(*) FROM customers WHERE deleted_at IS NULL AND new_city IS NOT NULL AND new_city <> '';
|
|||
|
|
|
|||
|
|
-- فرمت رمز عبور: bcrypt با $2y$ شروع میشود. اگر نه، hash دیگری است
|
|||
|
|
SELECT 'pw_bcrypt' AS metric, SUM(password LIKE '$2%') AS n FROM customers WHERE deleted_at IS NULL
|
|||
|
|
UNION ALL SELECT 'pw_other', SUM(password IS NOT NULL AND password <> '' AND password NOT LIKE '$2%') FROM customers WHERE deleted_at IS NULL
|
|||
|
|
UNION ALL SELECT 'pw_empty', SUM(password IS NULL OR password = '') FROM customers WHERE deleted_at IS NULL;
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- بخش ۸ — جداول پشتیبان: آیا ردیفی دارند که `customers` ندارد؟
|
|||
|
|
-- مرجع: §۱.۱ — قبل از نادیدهگرفتن باید شمرده شوند
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
SELECT '=== 8. BACKUP TABLES (safe to ignore?) ===' AS section;
|
|||
|
|
|
|||
|
|
SELECT 'customers' AS tbl, COUNT(*) AS n, CAST(MAX(id) AS CHAR) AS max_id FROM customers
|
|||
|
|
UNION ALL SELECT 'customers_copy1', COUNT(*), CAST(MAX(id) AS CHAR) FROM customers_copy1
|
|||
|
|
UNION ALL SELECT 'customers_copy2', COUNT(*), CAST(MAX(id) AS CHAR) FROM customers_copy2
|
|||
|
|
UNION ALL SELECT 'customers_test', COUNT(*), CAST(MAX(id) AS CHAR) FROM customers_test;
|
|||
|
|
|
|||
|
|
-- شناسههایی که در کپی هستند ولی در جدول اصلی نیستند → یعنی ردیف حذف شده
|
|||
|
|
SELECT 'ids_only_in_copy1' AS metric, COUNT(*) AS n
|
|||
|
|
FROM customers_copy1 k LEFT JOIN customers c ON c.id = k.id WHERE c.id IS NULL
|
|||
|
|
UNION ALL
|
|||
|
|
SELECT 'ids_only_in_copy2', COUNT(*)
|
|||
|
|
FROM customers_copy2 k LEFT JOIN customers c ON c.id = k.id WHERE c.id IS NULL;
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- بخش ۹ — تکفروشی (به تأخیر افتاده، §۷.۲) — فقط حجم، برای برنامهریزی آینده
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
SELECT '=== 9. RETAIL (deferred — size only) ===' AS section;
|
|||
|
|
|
|||
|
|
SELECT 'orders_orders' AS tbl, COUNT(*) AS live, SUM(deleted_at IS NOT NULL) AS soft_deleted FROM orders_orders
|
|||
|
|
UNION ALL SELECT 'orders_orderitem', COUNT(*), SUM(deleted_at IS NOT NULL) FROM orders_orderitem
|
|||
|
|
UNION ALL SELECT 'login', COUNT(*), SUM(deleted_at IS NOT NULL) FROM login;
|
|||
|
|
|
|||
|
|
-- 🔴 sts=7 در خرده «تحویل مشتری» است ولی در عمده «کنسل». چند ردیف درگیرند؟
|
|||
|
|
SELECT 'retail_sts' AS col, CAST(sts AS CHAR) AS val, COUNT(*) AS n
|
|||
|
|
FROM orders_orders WHERE deleted_at IS NULL GROUP BY sts ORDER BY sts;
|
|||
|
|
|
|||
|
|
SELECT '=== END ===' AS section;
|