{
  "assessmentTests": {
    "sql_test": {
      "name": "מבחן SQL",
      "desc": "30 שאלות תרחיש על סינון, joins, אגרגציה, subqueries ופונקציות חלון — גלו אם רמת ה-SQL שלכם תואמת למה שמשרות מתכוונות כשהן כותבות SQL proficiency.",
      "recommendation": "פרופיל כישורי ה-SQL שלך",
      "results": {
        "beginner": {
          "name": "מתחילים",
          "desc": "יש לך יכולת לכתוב משפט SELECT עובד ולסנן לפי כמה תנאים, אבל השאלות שפספסת מתקבצות סביב טיפול ב-NULL ומכניקת joins ולא סביב תחביר — השוואת עמודה ל-NULL עם =, מה LEFT JOIN באמת משמר, איך הגבולות של BETWEEN עובדים. זה לא עניין של להיות גרועים בבסיסי נתונים; אלה הכללים הספציפיים שמכשילים אנשים שלמדו SQL בניסוי וטעייה ולא מהסטנדרט. זה חשוב בעבודה כי כל אחד מהם הוא המקום שבו שאילתה מחזירה ספירת שורות שנראית הגיונית אבל שגויה.",
          "recommendation": "התחילו עם שלושה דברים, בסדר הזה: למה WHERE col = NULL אף פעם לא מתאים לשום דבר (ו-IS NULL נדרש במקום), איך INNER JOIN מוריד שורות ללא התאמה בעוד LEFT JOIN שומר אותן, והגבולות המדויקים ש-BETWEEN כולל. המדריך של Mode Analytics ל-SQL והתיעוד של PostgreSQL מכסים את שלושתם עם דוגמאות להרצה."
        },
        "intermediate": {
          "name": "בינוניים",
          "desc": "יש לך יכולת לטפל בנוחות בשאילתות דיווח יומיומיות — joins, GROUP BY, סינון פשוט — ולא תואטו על ידי עבודת דשבורד שגרתית או ניתוח אד-הוק. הפער בין כאן לבין מתקדם הוא בעיקר במה שקורה כשפסוקיות מתקשרות: פסוקית WHERE על הטבלה המצורפת שהופכת בשקט LEFT JOIN בחזרה ל-INNER JOIN, join שמכפיל ספירות שורות לפני שאגרגט מופעל עליהן, NOT IN שמחזיר בשקט כלום כי NULL אחד חמק לתוך ה-subquery. אלה סוגי הבאגים שעוברים בדיקה מהירה בעין ומתגלים רק כשמישהו משווה את הסכום לדוח אחר.",
          "recommendation": "התמקדו באיך פסוקיות מתקשרות ולא במה כל אחת עושה לבד: סינון WHERE על עמודות צד ימין של LEFT JOIN, הכפלת שורות מ-joins של אחד-לרבים לפני אגרגציה, ולמה NOT IN נשבר בנוכחות NULLs (EXISTS בדרך כלל לא). אחר כך HAVING מול WHERE, כי ההפרדה הזו מכשילה אנשים שכבר מכירים את שתי הפסוקיות בנפרד."
        },
        "advanced": {
          "name": "מתקדמים",
          "desc": "זו הרמה שרוב המשרות מתכוונות אליה כשהן כותבות \"SQL חזק\". יש לך יכולת לקרוא שאילתה עם מספר joins ולחזות את ספירת השורות שלה לפני הרצה, לדעת למה סט תוצאות השתנה ולא רק שהוא השתנה, ולהגיע ל-CTE או פונקציית חלון במקום subquery מקונן כשזה הכלי הברור יותר. מה שמפריד בין הרמה הזו לעליונה הוא הצד ההגנתי של העבודה: לדעת באיזו פונקציית דירוג להשתמש כשתיקו חשוב, מה transaction מבודד מסשן מקביל, ומה כלל ON DELETE חסר באמת עושה ברמת בסיס הנתונים.",
          "recommendation": "התקדמו לחלקים שמגנים על נתונים שאנשים אחרים גם נוגעים בהם: ההבדל בין RANK, DENSE_RANK ו-ROW_NUMBER בתיקו, מה COMMIT באמת הופך לגלוי ולמי, והתנהגות foreign key ב-DELETE. השתמשו בניוזלטר The Index או בצלילות העומק של SQL for Devs על פונקציות חלון ובידוד transactions כתחנה הבאה לשניהם."
        },
        "expert": {
          "name": "מומחים",
          "desc": "השגת ציון בראש כל חלק — סינון וסמנטיקת NULL, joins ופעולות קבוצה, אגרגציה ו-subqueries, ופונקציות חלון, CTEs ואילוצים. מבחינה מעשית, זה אומר שאפשר לתת לך שאילתת דוח עם מספר joins של מישהו זר ולהסביר למה היא מחזירה את ספירת השורות שהיא מחזירה, לא רק מה התחביר אומר שהיא צריכה לעשות, וזו המיומנות הקשה והיקרה יותר. ברמה הזו שפת השאילתות היא לעתים רחוקות הגורם המגביל; המגבלה היא בדרך כלל עיצוב הסכמה או גודל הנתונים מתחתיה.",
          "recommendation": "התשואות עכשיו הן בתוכניות ביצוע ועיצוב: קריאת פלט EXPLAIN לפני הנחה ששאילתה איטית, אסטרטגיית אינדקס כפשרה מול עלות כתיבה ולא כרווח חינמי, והחלטות נורמליזציה שמחזיקות מעמד ככל שסכמה גדלה. אם עוברים סינון לתפקיד, תארו באג שאילתה כמו הכפלת join או מלכודת NOT IN/NULL שמצאתם בפרודקשן במקום לנקוב בתכונות SQL — זה מדגים את החשיבה, לא רק את אוצר המילים."
        }
      },
      "questions": [
        {
          "question": "לטבלה יש עמודה nullable בשם age. מריצים SELECT * FROM users WHERE age = NULL. כמה שורות זה מחזיר, גם אם למספר שורות יש age מוגדר כ-NULL?",
          "options": [
            {
              "icon": "",
              "label": "כל שורה שבה age הוא NULL, כי = מתאים ל-NULL כמו לכל ערך אחר"
            },
            {
              "icon": "",
              "label": "אפס — השוואה של משהו ל-NULL עם = מייצרת UNKNOWN, אף פעם לא TRUE, אז אף שורה לא מתאימה; IS NULL נדרש במקום"
            },
            {
              "icon": "",
              "label": "שגיאת תחביר — NULL לא יכול להופיע בצד ימין של ="
            },
            {
              "icon": "",
              "label": "כל שורה בטבלה, כי השוואות NULL מוגדרות כברירת מחדל ל-TRUE"
            }
          ]
        },
        {
          "question": "מריצים SELECT DISTINCT department, role FROM employees. ממה DISTINCT מסיר כפילויות?",
          "options": [
            {
              "icon": "",
              "label": "מהשילוב של department ו-role יחד — שורה מוסרת רק אם שתי העמודות תואמות לשורה אחרת בדיוק"
            },
            {
              "icon": "",
              "label": "מערכי department כפולים בלבד, שומר כל role"
            },
            {
              "icon": "",
              "label": "מערכי role כפולים בלבד, שומר כל department"
            },
            {
              "icon": "",
              "label": "כלום — DISTINCT עובד רק עם עמודה בודדת"
            }
          ]
        },
        {
          "question": "שם עמודה מסונן עם WHERE name LIKE 'A_'. אילו מהערכים הבאים מתאימים: 'A', 'Al', 'Ana', 'Ally'?",
          "options": [
            {
              "icon": "",
              "label": "'A' — הקו התחתון הוא אופציונלי ומתאים לאפס תווים או יותר"
            },
            {
              "icon": "",
              "label": "'Al' — הקו התחתון מתאים לתו אחד בדיוק, אז LIKE 'A_' מתאים לכל מחרוזת בת שני תווים שמתחילה ב-A"
            },
            {
              "icon": "",
              "label": "'Ana' ו-'Ally' — הקו התחתון מתאים לכל מספר של תווים נגררים"
            },
            {
              "icon": "",
              "label": "כל ארבעת הערכים מתאימים, כי LIKE מתעלם מאורך"
            }
          ]
        },
        {
          "question": "עמודת price מסוננת עם WHERE price BETWEEN 10 AND 20. האם שורות עם price בדיוק 10 או בדיוק 20 נכללות?",
          "options": [
            {
              "icon": "",
              "label": "לא — BETWEEN לא כולל את שני הקצוות"
            },
            {
              "icon": "",
              "label": "כן — BETWEEN כולל את שני הקצוות, שווה ערך ל-price >= 10 AND price <= 20"
            },
            {
              "icon": "",
              "label": "רק price = 10 נכלל; הגבול העליון לא כלול"
            },
            {
              "icon": "",
              "label": "רק price = 20 נכלל; הגבול התחתון לא כלול"
            }
          ]
        },
        {
          "question": "לטבלה orders יש 10 שורות, ו-3 מהן עם shipped_date שהוא NULL. מה SELECT COUNT(*) FROM orders מחזיר, ומה SELECT COUNT(shipped_date) FROM orders מחזיר?",
          "options": [
            {
              "icon": "",
              "label": "10, ואז 10 — COUNT תמיד סופר שורות ללא קשר ל-NULLs"
            },
            {
              "icon": "",
              "label": "7, ואז 7 — שתי הצורות מדלגות על שורות NULL"
            },
            {
              "icon": "",
              "label": "10, ואז 7 — COUNT(*) סופר כל שורה, COUNT(column) סופר רק שורות שבהן העמודה הזו אינה NULL"
            },
            {
              "icon": "",
              "label": "10, ואז 3 — COUNT(column) סופר רק את ערכי ה-NULL"
            }
          ]
        },
        {
          "question": "מריצים SELECT name, salary FROM employees ORDER BY 2 DESC. למה ה-2 מתייחס?",
          "options": [
            {
              "icon": "",
              "label": "שגיאת תחביר — ORDER BY מקבל רק שמות עמודות, לא מספרים"
            },
            {
              "icon": "",
              "label": "השורה השנייה בתוצאה"
            },
            {
              "icon": "",
              "label": "ערך מילולי של 2, משמש כמכריע תיקו"
            },
            {
              "icon": "",
              "label": "העמודה השנייה ברשימת ה-SELECT, salary — ORDER BY מקבל מספר מיקום של עמודה כקיצור"
            }
          ]
        },
        {
          "question": "ב-SQL סטנדרטי, למה 'Ana' || ' ' || 'Lee' מחושב?",
          "options": [
            {
              "icon": "",
              "label": "שגיאת תחביר — ל-SQL אין אופרטור שרשור"
            },
            {
              "icon": "",
              "label": "3 — || מטופל כ-OR בוליאני ומחזיר ספירה"
            },
            {
              "icon": "",
              "label": "'AnaLee' — || משרשר בלי לשמר רווחים"
            },
            {
              "icon": "",
              "label": "'Ana Lee' — || הוא אופרטור שרשור המחרוזות הסטנדרטי ב-SQL"
            }
          ]
        },
        {
          "question": "מה מהבאים שווה ערך בדיוק ל-WHERE status IN ('open', 'pending', 'review')?",
          "options": [
            {
              "icon": "",
              "label": "WHERE status = 'open' AND status = 'pending' AND status = 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status != 'open' OR status != 'pending' OR status != 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status = 'open' OR status = 'pending' OR status = 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status LIKE 'open,pending,review'"
            }
          ]
        },
        {
          "question": "ל-customers יש 100 שורות; 20 מהן מעולם לא ביצעו הזמנה. מריצים SELECT c.id FROM customers c INNER JOIN orders o ON c.id = o.customer_id. האם 20 הלקוחות ללא הזמנות מופיעים בתוצאה?",
          "options": [
            {
              "icon": "",
              "label": "כן, פעם אחת כל אחד, עם o.id מוצג כ-NULL"
            },
            {
              "icon": "",
              "label": "כן, אבל רק אם הם גם מופיעים בפסוקית WHERE"
            },
            {
              "icon": "",
              "label": "לא — INNER JOIN מחזיר רק שורות שיש להן התאמה בשתי הטבלאות, אז לקוחות עם אפס הזמנות מוסרים לגמרי"
            },
            {
              "icon": "",
              "label": "כן, משוכפלים פעם אחת לכל עמודה ב-orders"
            }
          ]
        },
        {
          "question": "רוצים כל לקוח בין אם יש לו הזמנות ובין אם לא, אז כותבים SELECT c.id, o.total FROM customers c LEFT JOIN orders o ON c.id = o.customer_id WHERE o.total > 100. האם זה עדיין מחזיר לקוחות עם אפס הזמנות?",
          "options": [
            {
              "icon": "",
              "label": "לא — סינון על o.total בפסוקית WHERE מוחק את שורות ה-NULL ש-LEFT JOIN ייצר עבור לקוחות ללא התאמה, אז זה מתנהג כמו INNER JOIN"
            },
            {
              "icon": "",
              "label": "כן — LEFT JOIN תמיד משמר כל שורה מ-customers לא משנה מה בא אחר כך"
            },
            {
              "icon": "",
              "label": "כן, עם o.total מוצג כ-0 עבור לקוחות ללא הזמנות"
            },
            {
              "icon": "",
              "label": "לא — LEFT JOIN ממיר את עצמו בשקט ל-RIGHT JOIN כשמוסיפים פסוקית WHERE"
            }
          ]
        },
        {
          "question": "לטבלת employees יש עמודת id ועמודת manager_id שמצביעה על id של שורה אחרת. כדי לרשום כל עובד ליד שם המנהל שלו, מצרפים את הטבלה לעצמה: SELECT e.name, m.name FROM employees e JOIN employees m ON e.manager_id = m.id. איך קוראים לתבנית הזו?",
          "options": [
            {
              "icon": "",
              "label": "cross join — כל עובד מותאם לכל מנהל"
            },
            {
              "icon": "",
              "label": "recursive join — זה מביא את כל שרשרת הניהול"
            },
            {
              "icon": "",
              "label": "self-join — אותה טבלה מצורפת לעצמה באמצעות שני כינויים שונים"
            },
            {
              "icon": "",
              "label": "זה SQL לא תקין — טבלה לא יכולה להיות מצורפת לעצמה"
            }
          ]
        },
        {
          "question": "שתי שאילתות SELECT עם אותן עמודות משולבות באמצעות UNION. אם שתי השאילתות מחזירות שורה זהה, כמה עותקים של אותה שורה יופיעו בתוצאה הסופית?",
          "options": [
            {
              "icon": "",
              "label": "אחד — UNION מסיר שורות כפולות מהתוצאה המשולבת; UNION ALL היה שומר את שני העותקים"
            },
            {
              "icon": "",
              "label": "שניים — UNION שומר כל שורה משתי השאילתות"
            },
            {
              "icon": "",
              "label": "אפס — UNION מסיר כל שורה שמופיעה בשתי השאילתות"
            },
            {
              "icon": "",
              "label": "זה תלוי באיזו שאילתה השורה הופיעה קודם"
            }
          ]
        },
        {
          "question": "בטבלה sizes יש 3 שורות ובטבלה colors יש 4 שורות. כמה שורות מחזירה השאילתה SELECT * FROM sizes CROSS JOIN colors?",
          "options": [
            {
              "icon": "",
              "label": "7 — CROSS JOIN מחבר את מספרי השורות יחד"
            },
            {
              "icon": "",
              "label": "12 — CROSS JOIN מחזיר כל שילוב אפשרי של שורות משתי הטבלאות (3 x 4)"
            },
            {
              "icon": "",
              "label": "3 — CROSS JOIN מחזיר שורה אחת לכל שורה בטבלה הראשונה"
            },
            {
              "icon": "",
              "label": "0 — CROSS JOIN דורש תנאי ON אחרת לא מוחזר דבר"
            }
          ]
        },
        {
          "question": "בטבלה orders יש שורה אחת להזמנה #100, ובטבלה order_items יש 3 שורות להזמנה #100 (אחת לכל פריט). מריצים את השאילתה SELECT o.id, o.total FROM orders o JOIN order_items i ON o.id = i.order_id WHERE o.id = 100. כמה שורות מוחזרות עבור הזמנה #100?",
          "options": [
            {
              "icon": "",
              "label": "3 — ה-join מייצר שורת פלט אחת לכל שורה תואמת ב-order_items, כך שהשורה היחידה של הזמנה #100 חוזרת פעם אחת לכל פריט"
            },
            {
              "icon": "",
              "label": "1 — ב-orders יש רק שורה אחת להזמנה #100, אז ה-join לא יכול לייצר יותר"
            },
            {
              "icon": "",
              "label": "4 — שורה אחת להזמנה ועוד אחת לכל פריט"
            },
            {
              "icon": "",
              "label": "0 — חיבור טבלה בת שורה אחת לטבלה בת שלוש שורות על מפתח לא ייחודי נכשל"
            }
          ]
        },
        {
          "question": "SELECT c.name, o.id FROM customers c RIGHT JOIN orders o ON c.id = o.customer_id מחזירה את אותן שורות כמו איזו מהשאילתות הבאות?",
          "options": [
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM customers c INNER JOIN orders o ON c.id = o.customer_id"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM orders o LEFT JOIN customers c ON c.id = o.customer_id — החלפת סדר הטבלאות ושימוש ב-LEFT JOIN במקום RIGHT JOIN שקולים"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM customers c LEFT JOIN orders o ON c.id = o.customer_id"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM orders o CROSS JOIN customers c"
            }
          ]
        },
        {
          "question": "ב-SQL סטנדרטי, מריצים SELECT department, name, AVG(salary) FROM employees GROUP BY department. האם זו שאילתה תקינה?",
          "options": [
            {
              "icon": "",
              "label": "כן — GROUP BY צריך לכלול רק את department כי היא מופיעה ראשונה"
            },
            {
              "icon": "",
              "label": "לא — name נבחרת אך לא מצוברת ולא מופיעה ב-GROUP BY, ו-SQL סטנדרטי דורש שכל עמודה לא מצוברת שנבחרת תופיע בפסוקית GROUP BY"
            },
            {
              "icon": "",
              "label": "כן — SQL בוחר אוטומטית name שרירותי אחד לכל מחלקה"
            },
            {
              "icon": "",
              "label": "לא — לא ניתן לשלב AVG() עם GROUP BY באותה שאילתה"
            }
          ]
        },
        {
          "question": "רוצים מחלקות שבהן השכר הממוצע עולה על 80000. איזו פסוקית מסננת לפי ערך מצובר כמו AVG(salary) אחרי קיבוץ — WHERE או HAVING?",
          "options": [
            {
              "icon": "",
              "label": "WHERE — HAVING משמש רק עם שאילתות UNION"
            },
            {
              "icon": "",
              "label": "שתיהן עובדות באופן זהה עם פונקציות צבירה"
            },
            {
              "icon": "",
              "label": "אף אחת — סינון צבירה דורש תת-שאילתה"
            },
            {
              "icon": "",
              "label": "HAVING — WHERE מסנן שורות בודדות לפני הקיבוץ, HAVING מסנן קבוצות אחרי הצבירה"
            }
          ]
        },
        {
          "question": "כותבים SELECT salary * 1.1 AS new_salary FROM employees WHERE new_salary > 50000. האם זה רץ?",
          "options": [
            {
              "icon": "",
              "label": "כן — כינויים שמוגדרים ב-SELECT תמיד זמינים ל-WHERE באותה שאילתה"
            },
            {
              "icon": "",
              "label": "כן, אבל רק עבור כינויים מספריים"
            },
            {
              "icon": "",
              "label": "לא — AS אסור בתוך שאילתה עם סינון WHERE"
            },
            {
              "icon": "",
              "label": "לא — WHERE מוערך לפני ש-SELECT מקצה את הכינוי new_salary, אז הכינוי עדיין לא קיים בנקודה זו בביצוע"
            }
          ]
        },
        {
          "question": "SELECT name FROM employees e WHERE salary > (SELECT AVG(salary) FROM employees WHERE department = e.department). למה זו נקראת תת-שאילתה מתואמת?",
          "options": [
            {
              "icon": "",
              "label": "כי היא משתמשת ב-JOIN במקום פסוקית WHERE"
            },
            {
              "icon": "",
              "label": "תת-השאילתה הפנימית מתייחסת ל-e.department מהשאילתה החיצונית, אז היא חייבת להיות מוערכת מחדש עבור כל שורה שהשאילתה החיצונית בוחנת"
            },
            {
              "icon": "",
              "label": "כי היא מחזירה יותר מעמודה אחת"
            },
            {
              "icon": "",
              "label": "כי היא רצה בדיוק פעם אחת לפני שהשאילתה החיצונית מתחילה"
            }
          ]
        },
        {
          "question": "תת-שאילתה SELECT manager_id FROM employees מחזירה כמה ערכי NULL יחד עם מזהים אמיתיים. מריצים SELECT name FROM employees WHERE id NOT IN (SELECT manager_id FROM employees). מה קורה?",
          "options": [
            {
              "icon": "",
              "label": "היא מחזירה כל עובד שאינו מנהל, תוך התעלמות מה-NULL-ים"
            },
            {
              "icon": "",
              "label": "היא מחזירה אפס שורות — NULL בודד ברשימת NOT IN הופך כל השוואה ל-UNKNOWN, כך שאף שורה לא יכולה לעמוד בתנאי"
            },
            {
              "icon": "",
              "label": "היא מעלה שגיאה כי NOT IN לא יכול לשמש עם תת-שאילתות"
            },
            {
              "icon": "",
              "label": "היא מחזירה כל עובד, כי NULL מטופל כתו כללי"
            }
          ]
        },
        {
          "question": "SELECT name FROM customers c WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id). מה זה מחזיר?",
          "options": [
            {
              "icon": "",
              "label": "כל לקוח שיש לו לפחות שורה אחת ב-orders — EXISTS רק בודק אם תת-השאילתה מחזירה שורות כלשהן, לא אילו ערכים הן מכילות"
            },
            {
              "icon": "",
              "label": "כל לקוח, כי SELECT 1 תמיד מחזיר true"
            },
            {
              "icon": "",
              "label": "שגיאה, כי תת-השאילתה בוחרת מספר במקום שם עמודה"
            },
            {
              "icon": "",
              "label": "רק לקוחות עם בדיוק הזמנה אחת"
            }
          ]
        },
        {
          "question": "כותבים SELECT name, (SELECT order_id FROM orders WHERE customer_id = c.id) AS last_order FROM customers c, וללקוח מסוים יש 3 שורות ב-orders. מה קורה כשהשאילתה רצה?",
          "options": [
            {
              "icon": "",
              "label": "היא מחזירה את ה-order_id התואם הראשון ומתעלמת בשקט מהשניים האחרים"
            },
            {
              "icon": "",
              "label": "היא מחזירה רשימה מופרדת בפסיקים של כל שלושת ה-order_id-ים"
            },
            {
              "icon": "",
              "label": "היא מחזירה 3 שורות עבור אותו לקוח, אחת לכל הזמנה"
            },
            {
              "icon": "",
              "label": "היא מעלה שגיאה בזמן ריצה — תת-שאילתה סקלרית ברשימת ה-SELECT חייבת להחזיר לכל היותר שורה אחת, וזו מחזירה שלוש"
            }
          ]
        },
        {
          "question": "ארבע שורות קשורות בתיקו לציון הגבוה ביותר. בשימוש ב-RANK() ORDER BY score DESC, כולן מקבלות דירוג 1. איזה דירוג מקבלת השורה הבאה?",
          "options": [
            {
              "icon": "",
              "label": "5 — RANK() משאיר פער השווה למספר השורות הקשורות לפני שממשיך"
            },
            {
              "icon": "",
              "label": "2 — RANK() תמיד מתקדם באחד בדיוק אחרי כל תיקו"
            },
            {
              "icon": "",
              "label": "1 — כל שורה שאחריה גם מקבלת דירוג 1"
            },
            {
              "icon": "",
              "label": "4 — RANK() מתחיל לספור מחדש ממספר התיקואים"
            }
          ]
        },
        {
          "question": "ארבע שורות קשורות בתיקו לציון הגבוה ביותר. בשימוש ב-DENSE_RANK() ORDER BY score DESC, כולן מקבלות דירוג 1. איזה דירוג מקבלת השורה הבאה?",
          "options": [
            {
              "icon": "",
              "label": "5 — DENSE_RANK() מתנהג בדיוק כמו RANK()"
            },
            {
              "icon": "",
              "label": "1 — DENSE_RANK() מקצה את אותו דירוג לכל השורות הנותרות"
            },
            {
              "icon": "",
              "label": "2 — DENSE_RANK() לעולם לא משאיר פערים, אז הערך הייחודי הבא תמיד מקבל את הדירוג הרצוף הבא"
            },
            {
              "icon": "",
              "label": "3 — DENSE_RANK() מדלג על דירוג אחד לכל קבוצת תיקו"
            }
          ]
        },
        {
          "question": "SUM(amount) OVER (PARTITION BY region ORDER BY amount) נוסף לשאילתה. מה עושה PARTITION BY region כאן?",
          "options": [
            {
              "icon": "",
              "label": "זה מתחיל את הסכום המצטבר מחדש בנפרד לכל אזור, במקום לצבור על פני כל סט התוצאות"
            },
            {
              "icon": "",
              "label": "זה מסנן את התוצאות לאזור יחיד"
            },
            {
              "icon": "",
              "label": "זה מקבץ ומכווץ את השורות לאחת לכל אזור, כמו GROUP BY"
            },
            {
              "icon": "",
              "label": "זה ממיין את האזורים לפי סדר אלפביתי לפני הסיכום"
            }
          ]
        },
        {
          "question": "ROW_NUMBER() OVER (ORDER BY score DESC) מוחל על חמש שורות, שתיים מהן קשורות בדיוק באותו ציון. האם שתי שורות יכולות לקבל את אותו מספר שורה?",
          "options": [
            {
              "icon": "",
              "label": "כן — שורות קשורות תמיד חולקות את אותו מספר שורה"
            },
            {
              "icon": "",
              "label": "רק אם משתמשים גם ב-PARTITION BY"
            },
            {
              "icon": "",
              "label": "זה תלוי אם התיקו הוא במיקום הראשון או האחרון"
            },
            {
              "icon": "",
              "label": "לא — ROW_NUMBER() תמיד מקצה מספר שלם ייחודי ועולה בהחלט לכל שורה, גם כשערכים קשורים"
            }
          ]
        },
        {
          "question": "WITH high_earners AS (SELECT * FROM employees WHERE salary > 100000) SELECT department, COUNT(*) FROM high_earners GROUP BY department. מהו high_earners?",
          "options": [
            {
              "icon": "",
              "label": "ביטוי טבלה משותף (CTE) — סט תוצאות זמני בעל שם שיתר השאילתה יכול להתייחס אליו כמו לטבלה"
            },
            {
              "icon": "",
              "label": "טבלה קבועה שנוצרת במסד הנתונים"
            },
            {
              "icon": "",
              "label": "תצוגה שנשארת אחרי שהשאילתה מסתיימת"
            },
            {
              "icon": "",
              "label": "פרוצדורה מאוחסנת שצריך לקרוא לה בנפרד"
            }
          ]
        },
        {
          "question": "עמודה מוגדרת כ-PRIMARY KEY. האם אפשר להכניס שורה שבה העמודה הזו היא NULL?",
          "options": [
            {
              "icon": "",
              "label": "כן — PRIMARY KEY אוכף רק ייחודיות, לא NOT NULL"
            },
            {
              "icon": "",
              "label": "כן, אבל רק שורת NULL אחת מותרת, כמו אילוץ UNIQUE"
            },
            {
              "icon": "",
              "label": "לא — עמודת PRIMARY KEY היא באופן מרומז NOT NULL, אז הכנסת NULL אליה נדחית"
            },
            {
              "icon": "",
              "label": "זה תלוי אם לעמודה יש גם ערך ברירת מחדל"
            }
          ]
        },
        {
          "question": "בתוך טרנזקציה פתוחה, מריצים UPDATE אבל עדיין לא הריצו COMMIT. מחיבור שני ונפרד למסד הנתונים, האם העדכון הזה נראה?",
          "options": [
            {
              "icon": "",
              "label": "כן — כל החיבורים רואים כל כתיבה ברגע שהיא רצה"
            },
            {
              "icon": "",
              "label": "כן, אבל רק אם החיבור השני גם פותח טרנזקציה"
            },
            {
              "icon": "",
              "label": "זה תלוי רק באיזו טבלה עודכנה"
            },
            {
              "icon": "",
              "label": "לא — שינוי שלא אושר נראה רק בתוך הטרנזקציה שביצעה אותו, עד ש-COMMIT הופך אותו לעמיד ונראה לאחרים"
            }
          ]
        },
        {
          "question": "ל-products.category_id יש אילוץ FOREIGN KEY שמפנה ל-categories.id. מנסים למחוק שורה מ-categories שעדיין יש מוצרים שמצביעים אליה, ללא כלל ON DELETE מוגדר. מה קורה?",
          "options": [
            {
              "icon": "",
              "label": "שורת הקטגוריה נמחקת וערכי products.category_id התואמים מוגדרים אוטומטית ל-NULL"
            },
            {
              "icon": "",
              "label": "שורת הקטגוריה נמחקת וכל מוצר שהפנה אליה נמחק גם"
            },
            {
              "icon": "",
              "label": "פעולת ה-DELETE נדחית — התנהגות ברירת המחדל של מפתח זר חוסמת מחיקת שורה מוזכרת כל עוד שורות תלויות עדיין מצביעות אליה"
            },
            {
              "icon": "",
              "label": "פעולת ה-DELETE מצליחה בשקט, ומשאירה את category_id של המוצרים מצביע לקטגוריה שכבר לא קיימת"
            }
          ]
        }
      ],
      "optionOrderVersion": "e0466e547cfd8a45"
    }
  }
}
