[
  {
    "language": "JS",
    "title": "두 수의 합",
    "difficulty": "EASY",
    "topic": "javascript",
    "description": "정수 두 개 a, b를 받아 그 합을 돌려주는 함수를 완성하세요.\n\n예) solution(1, 2) → 3\n\n힌트: return 문으로 값을 돌려줍니다. return이 없으면 undefined가 나갑니다.",
    "starterCode": "function solution(a, b) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "1 + 2 = 3",
        "args": [
          1,
          2
        ],
        "expected": 3
      },
      {
        "name": "0 + 0 = 0",
        "args": [
          0,
          0
        ],
        "expected": 0
      },
      {
        "name": "음수도 된다 (-5 + 3)",
        "args": [
          -5,
          3
        ],
        "expected": -2
      },
      {
        "name": "큰 수 (10000 + 23456)",
        "args": [
          10000,
          23456
        ],
        "expected": 33456
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "짝수인지 판별하기",
    "difficulty": "EASY",
    "topic": "javascript",
    "description": "정수 n이 짝수면 true, 홀수면 false를 돌려주세요.\n\n힌트: 나머지 연산자 %를 쓰면 2로 나눈 나머지를 알 수 있습니다. 0은 짝수입니다.",
    "starterCode": "function solution(n) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "4는 짝수",
        "args": [
          4
        ],
        "expected": true
      },
      {
        "name": "7은 홀수",
        "args": [
          7
        ],
        "expected": false
      },
      {
        "name": "0은 짝수",
        "args": [
          0
        ],
        "expected": true
      },
      {
        "name": "-3은 홀수",
        "args": [
          -3
        ],
        "expected": false
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "문자열 뒤집기",
    "difficulty": "EASY",
    "topic": "javascript",
    "description": "문자열 s를 거꾸로 뒤집어 돌려주세요.\n\n예) solution('hello') → 'olleh'\n\n힌트: 문자열을 split('')으로 배열로 만들고 reverse() 후 join('')으로 다시 붙일 수 있습니다.",
    "starterCode": "function solution(s) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "'hello' → 'olleh'",
        "args": [
          "hello"
        ],
        "expected": "olleh"
      },
      {
        "name": "한 글자는 그대로",
        "args": [
          "a"
        ],
        "expected": "a"
      },
      {
        "name": "빈 문자열",
        "args": [
          ""
        ],
        "expected": ""
      },
      {
        "name": "한글도 된다",
        "args": [
          "가나다"
        ],
        "expected": "다나가"
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "배열에서 가장 큰 수 찾기",
    "difficulty": "EASY",
    "topic": "javascript",
    "description": "숫자 배열 numbers에서 가장 큰 값을 돌려주세요. 배열은 항상 1개 이상입니다.\n\n힌트: Math.max(...numbers)처럼 펼침 연산자(...)를 쓰거나, 반복문으로 직접 비교할 수 있습니다.",
    "starterCode": "function solution(numbers) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "[1, 5, 3] → 5",
        "args": [
          [
            1,
            5,
            3
          ]
        ],
        "expected": 5
      },
      {
        "name": "원소 하나",
        "args": [
          [
            42
          ]
        ],
        "expected": 42
      },
      {
        "name": "전부 음수",
        "args": [
          [
            -1,
            -9,
            -4
          ]
        ],
        "expected": -1
      },
      {
        "name": "중복이 있어도",
        "args": [
          [
            7,
            7,
            2
          ]
        ],
        "expected": 7
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "1부터 n까지 더하기",
    "difficulty": "EASY",
    "topic": "javascript",
    "description": "1부터 n까지의 합을 돌려주세요. n은 1 이상입니다.\n\n예) solution(5) → 15  (1+2+3+4+5)\n\n힌트: for문으로 더해도 되고, 공식 n*(n+1)/2를 써도 됩니다.",
    "starterCode": "function solution(n) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "n=5 → 15",
        "args": [
          5
        ],
        "expected": 15
      },
      {
        "name": "n=1 → 1",
        "args": [
          1
        ],
        "expected": 1
      },
      {
        "name": "n=100 → 5050",
        "args": [
          100
        ],
        "expected": 5050
      },
      {
        "name": "n=10 → 55",
        "args": [
          10
        ],
        "expected": 55
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "모음 개수 세기",
    "difficulty": "NORMAL",
    "topic": "javascript",
    "description": "영어 소문자 문자열 s에서 모음(a, e, i, o, u)이 몇 개인지 세어 돌려주세요.\n\n예) solution('hello') → 2\n\n힌트: 문자열도 for...of로 한 글자씩 돌 수 있습니다. includes()가 유용합니다.",
    "starterCode": "function solution(s) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "'hello' → 2",
        "args": [
          "hello"
        ],
        "expected": 2
      },
      {
        "name": "모음 없음",
        "args": [
          "xyz"
        ],
        "expected": 0
      },
      {
        "name": "전부 모음",
        "args": [
          "aeiou"
        ],
        "expected": 5
      },
      {
        "name": "빈 문자열",
        "args": [
          ""
        ],
        "expected": 0
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "배열에서 짝수만 골라내기",
    "difficulty": "NORMAL",
    "topic": "javascript",
    "description": "숫자 배열에서 짝수만 순서를 유지한 채 새 배열로 돌려주세요.\n\n예) solution([1,2,3,4]) → [2, 4]\n\n힌트: filter()는 조건을 만족하는 원소만 모아 새 배열을 만듭니다. 원본은 바뀌지 않습니다.",
    "starterCode": "function solution(numbers) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "[1,2,3,4] → [2,4]",
        "args": [
          [
            1,
            2,
            3,
            4
          ]
        ],
        "expected": [
          2,
          4
        ]
      },
      {
        "name": "짝수 없음",
        "args": [
          [
            1,
            3,
            5
          ]
        ],
        "expected": []
      },
      {
        "name": "빈 배열",
        "args": [
          []
        ],
        "expected": []
      },
      {
        "name": "0도 짝수",
        "args": [
          [
            0,
            1
          ]
        ],
        "expected": [
          0
        ]
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "FizzBuzz",
    "difficulty": "NORMAL",
    "topic": "javascript",
    "description": "1부터 n까지를 배열로 돌려주되,\n3의 배수는 'Fizz', 5의 배수는 'Buzz', 3과 5의 공배수는 'FizzBuzz'로 바꿔 넣으세요.\n그 외는 숫자 그대로(문자열 아님) 넣습니다.\n\n예) solution(5) → [1, 2, 'Fizz', 4, 'Buzz']\n\n힌트: 15의 배수를 가장 먼저 검사해야 합니다. 순서를 바꾸면 'FizzBuzz'가 절대 나오지 않습니다.",
    "starterCode": "function solution(n) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "n=5",
        "args": [
          5
        ],
        "expected": [
          1,
          2,
          "Fizz",
          4,
          "Buzz"
        ]
      },
      {
        "name": "n=15 (마지막이 FizzBuzz)",
        "args": [
          15
        ],
        "expected": [
          1,
          2,
          "Fizz",
          4,
          "Buzz",
          "Fizz",
          7,
          8,
          "Fizz",
          "Buzz",
          11,
          "Fizz",
          13,
          14,
          "FizzBuzz"
        ]
      },
      {
        "name": "n=1",
        "args": [
          1
        ],
        "expected": [
          1
        ]
      },
      {
        "name": "n=3",
        "args": [
          3
        ],
        "expected": [
          1,
          2,
          "Fizz"
        ]
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "중복 제거하기",
    "difficulty": "NORMAL",
    "topic": "javascript",
    "description": "배열에서 중복된 값을 없애고, 처음 나온 순서를 유지한 새 배열을 돌려주세요.\n\n예) solution([1,2,2,3,1]) → [1, 2, 3]\n\n힌트: Set은 중복을 자동으로 없애 줍니다. [...new Set(arr)]로 배열로 되돌릴 수 있습니다.",
    "starterCode": "function solution(numbers) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "[1,2,2,3,1] → [1,2,3]",
        "args": [
          [
            1,
            2,
            2,
            3,
            1
          ]
        ],
        "expected": [
          1,
          2,
          3
        ]
      },
      {
        "name": "중복 없음",
        "args": [
          [
            1,
            2,
            3
          ]
        ],
        "expected": [
          1,
          2,
          3
        ]
      },
      {
        "name": "전부 같은 값",
        "args": [
          [
            5,
            5,
            5
          ]
        ],
        "expected": [
          5
        ]
      },
      {
        "name": "빈 배열",
        "args": [
          []
        ],
        "expected": []
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "회문(팰린드롬) 판별",
    "difficulty": "NORMAL",
    "topic": "javascript",
    "description": "문자열이 앞뒤 어느 쪽에서 읽어도 같으면 true, 아니면 false를 돌려주세요.\n대소문자는 구분하지 않고, 공백은 무시합니다.\n\n예) solution('level') → true, solution('a b a') → true\n\n힌트: 먼저 소문자로 바꾸고 공백을 없앤 다음, 뒤집은 것과 비교하세요. replaceAll(' ', '')이 쓸 만합니다.",
    "starterCode": "function solution(s) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "'level' → true",
        "args": [
          "level"
        ],
        "expected": true
      },
      {
        "name": "'hello' → false",
        "args": [
          "hello"
        ],
        "expected": false
      },
      {
        "name": "대소문자 무시 'Level'",
        "args": [
          "Level"
        ],
        "expected": true
      },
      {
        "name": "공백 무시 'a b a'",
        "args": [
          "a b a"
        ],
        "expected": true
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "단어 개수 세기 (객체 다루기)",
    "difficulty": "HARD",
    "topic": "javascript",
    "description": "공백으로 구분된 문자열에서 각 단어가 몇 번 나오는지 세어 객체로 돌려주세요.\n\n예) solution('a b a') → { a: 2, b: 1 }\n빈 문자열이면 빈 객체 {} 를 돌려주세요.\n\n힌트: split(' ')으로 나누고, 객체에 obj[word] = (obj[word] || 0) + 1 패턴을 쓰면 됩니다.\n(왜 || 0 이 필요할까? 처음 보는 단어면 obj[word]가 undefined이고, undefined + 1은 NaN이기 때문입니다.)",
    "starterCode": "function solution(sentence) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "'a b a'",
        "args": [
          "a b a"
        ],
        "expected": {
          "a": 2,
          "b": 1
        }
      },
      {
        "name": "단어 하나",
        "args": [
          "hello"
        ],
        "expected": {
          "hello": 1
        }
      },
      {
        "name": "빈 문자열 → {}",
        "args": [
          ""
        ],
        "expected": {}
      },
      {
        "name": "전부 다른 단어",
        "args": [
          "x y z"
        ],
        "expected": {
          "x": 1,
          "y": 1,
          "z": 1
        }
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JS",
    "title": "정렬해서 두 번째로 큰 수 찾기",
    "difficulty": "HARD",
    "topic": "javascript",
    "description": "배열에서 (중복을 제외하고) 두 번째로 큰 수를 돌려주세요.\n두 번째로 큰 수가 없으면 null을 돌려주세요.\n\n예) solution([3,1,3,2]) → 2  (중복 제외하면 3,2,1 이므로 두 번째는 2)\n\n힌트: 중복을 먼저 없애고 내림차순 정렬하세요.\n주의! sort()는 기본이 '문자열' 정렬이라 [10, 9]를 [10, 9]가 아니라 [10, 9]... 헷갈립니다.\n숫자는 반드시 sort((a, b) => b - a)처럼 비교 함수를 줘야 합니다.",
    "starterCode": "function solution(numbers) {\n  // 여기에 코드를 작성하세요\n}",
    "functionName": "solution",
    "tests": [
      {
        "name": "[3,1,3,2] → 2",
        "args": [
          [
            3,
            1,
            3,
            2
          ]
        ],
        "expected": 2
      },
      {
        "name": "전부 같으면 null",
        "args": [
          [
            5,
            5,
            5
          ]
        ],
        "expected": null
      },
      {
        "name": "두 자리 수 주의 [10, 9]",
        "args": [
          [
            10,
            9
          ]
        ],
        "expected": 9
      },
      {
        "name": "원소 하나면 null",
        "args": [
          [
            1
          ]
        ],
        "expected": null
      }
    ],
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JAVA",
    "title": "두 수 중 큰 값 돌려주기",
    "difficulty": "EASY",
    "topic": "java-basics",
    "description": "정수 두 개 중 더 큰 값을 돌려주는 메서드를 완성하세요. 같으면 그 값을 돌려줍니다.\n\n이 문제는 자동채점이 없습니다. 코드를 제출하면 멘토가 직접 읽고 피드백합니다.\n제출 전 IntelliJ에서 직접 실행해 확인해 보세요.\n\n힌트: if문으로 풀어도 되고 Math.max를 써도 됩니다. 둘 다 해보고 어느 쪽이 읽기 좋은지 생각해 보세요.",
    "starterCode": "public class Solution {\n\n    public int solution(int a, int b) {\n        // 여기에 코드를 작성하세요\n        return 0;\n    }\n}",
    "functionName": null,
    "tests": null,
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JAVA",
    "title": "배열의 합 구하기",
    "difficulty": "EASY",
    "topic": "java-basics",
    "description": "int 배열의 모든 원소를 더한 값을 돌려주세요. 빈 배열이면 0입니다.\n\n이 문제는 자동채점이 없습니다 — 멘토가 코드를 읽고 피드백합니다.\n\n힌트: 향상된 for문(for (int n : numbers))을 쓰면 인덱스 실수를 줄일 수 있습니다.",
    "starterCode": "public class Solution {\n\n    public int solution(int[] numbers) {\n        // 여기에 코드를 작성하세요\n        return 0;\n    }\n}",
    "functionName": null,
    "tests": null,
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JAVA",
    "title": "문자열이 비었는지 안전하게 검사하기",
    "difficulty": "EASY",
    "topic": "java-basics",
    "description": "문자열이 null이거나, 비어 있거나, 공백뿐이면 true를 돌려주세요. 그 외에는 false입니다.\n\n예) null → true, \"\" → true, \"   \" → true, \" a \" → false\n\n힌트: null 검사를 가장 먼저 해야 합니다. 순서를 바꾸면 NullPointerException이 납니다 —\n왜 그런지 설명할 수 있게 되는 것이 이 문제의 진짜 목표입니다. isBlank()를 찾아보세요.",
    "starterCode": "public class Solution {\n\n    public boolean solution(String s) {\n        // 여기에 코드를 작성하세요\n        return false;\n    }\n}",
    "functionName": null,
    "tests": null,
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JAVA",
    "title": "1부터 n까지 짝수만 더하기",
    "difficulty": "NORMAL",
    "topic": "java-basics",
    "description": "1부터 n까지의 정수 중 짝수만 더한 값을 돌려주세요.\n\n예) solution(10) → 30  (2+4+6+8+10)\n\n힌트: for문의 증가식을 i += 2로 두면 짝수만 밟을 수 있습니다.\nif로 걸러내는 방식과 비교해 보고, 어느 쪽이 더 좋은지 근거를 들어 설명해 보세요.",
    "starterCode": "public class Solution {\n\n    public int solution(int n) {\n        // 여기에 코드를 작성하세요\n        return 0;\n    }\n}",
    "functionName": null,
    "tests": null,
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JAVA",
    "title": "문자열 뒤집기 (StringBuilder)",
    "difficulty": "NORMAL",
    "topic": "java-basics",
    "description": "문자열을 거꾸로 뒤집어 돌려주세요.\n\n힌트: StringBuilder에는 reverse()가 있습니다.\n생각해 볼 것 — String을 +로 계속 이어 붙이며 뒤집으면 왜 느릴까요?\n(자바의 String은 한 번 만들면 바뀌지 않는다 = 불변. 이어 붙일 때마다 새 객체가 생깁니다.)\n제출할 때 이 이유를 주석으로 적어 주세요.",
    "starterCode": "public class Solution {\n\n    public String solution(String s) {\n        // 여기에 코드를 작성하세요\n        return \"\";\n    }\n}",
    "functionName": null,
    "tests": null,
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JAVA",
    "title": "배열에서 최댓값 찾기",
    "difficulty": "NORMAL",
    "topic": "java-basics",
    "description": "int 배열에서 가장 큰 값을 돌려주세요. 배열은 항상 1개 이상입니다.\n\n힌트: 최댓값의 시작값을 0으로 두면 안 됩니다 — 전부 음수인 배열에서 틀립니다.\n첫 원소(numbers[0])로 시작하세요. 이런 실수를 '경계 조건 버그'라고 부릅니다.",
    "starterCode": "public class Solution {\n\n    public int solution(int[] numbers) {\n        // 여기에 코드를 작성하세요\n        return 0;\n    }\n}",
    "functionName": null,
    "tests": null,
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JAVA",
    "title": "단어 개수 세기 (Map 다루기)",
    "difficulty": "HARD",
    "topic": "java-basics",
    "description": "공백으로 구분된 문장에서 각 단어의 등장 횟수를 Map<String, Integer>로 돌려주세요.\n\n예) \"a b a\" → {a=2, b=1}\n\n힌트: split(\" \")으로 나눈 뒤 Map에 넣습니다.\nmap.getOrDefault(word, 0) + 1 패턴을 찾아보세요 — merge()로도 됩니다.\n빈 문자열일 때 split이 무엇을 돌려주는지 직접 찍어 보고 처리하세요.",
    "starterCode": "import java.util.HashMap;\nimport java.util.Map;\n\npublic class Solution {\n\n    public Map<String, Integer> solution(String sentence) {\n        // 여기에 코드를 작성하세요\n        return new HashMap<>();\n    }\n}",
    "functionName": null,
    "tests": null,
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "JAVA",
    "title": "학생 목록을 점수순으로 정렬하기",
    "difficulty": "HARD",
    "topic": "java-basics",
    "description": "Student(name, score) 목록을 점수가 높은 순으로 정렬해 돌려주세요.\n점수가 같으면 이름 오름차순으로 정렬합니다.\n\n힌트: list.sort(Comparator.comparingInt(Student::getScore).reversed().thenComparing(Student::getName))\n메서드 참조(::)와 Comparator 조합을 익히는 문제입니다.\n한 줄로 쓰기 전에, 익명 클래스로 먼저 써 보고 무엇이 줄어드는지 비교해 보세요.",
    "starterCode": "import java.util.Comparator;\nimport java.util.List;\n\npublic class Solution {\n\n    public static class Student {\n        private final String name;\n        private final int score;\n\n        public Student(String name, int score) {\n            this.name = name;\n            this.score = score;\n        }\n\n        public String getName() { return name; }\n        public int getScore() { return score; }\n    }\n\n    public List<Student> solution(List<Student> students) {\n        // 여기에 코드를 작성하세요\n        return students;\n    }\n}",
    "functionName": null,
    "tests": null,
    "setupSql": null,
    "sqlExpected": null
  },
  {
    "language": "SQL",
    "title": "모든 직원 조회하기 (SELECT *)",
    "difficulty": "EASY",
    "topic": "sql",
    "description": "employee 테이블의 모든 행, 모든 컬럼을 조회하세요.\n\n문제 아래 [데이터 살펴보기]에서 테이블 구조와 데이터를 먼저 확인해 보세요.\n\n힌트: SELECT * 는 \"모든 컬럼\"이라는 뜻입니다. FROM 뒤에 테이블 이름을 씁니다.\nSQL 문장 끝에는 세미콜론(;)을 붙이는 습관을 들이세요.",
    "starterCode": "-- 여기에 SQL을 작성하세요\nSELECT ",
    "functionName": null,
    "tests": null,
    "setupSql": "CREATE TABLE department (\n  id   INTEGER PRIMARY KEY,   -- 부서 번호\n  name TEXT NOT NULL          -- 부서 이름\n);\n\nCREATE TABLE employee (\n  id          INTEGER PRIMARY KEY,  -- 사번\n  name        TEXT NOT NULL,        -- 이름\n  dept_id     INTEGER NOT NULL,     -- 소속 부서 번호 (department.id)\n  salary      INTEGER NOT NULL,     -- 연봉 (만원)\n  joined_year INTEGER NOT NULL      -- 입사 연도\n);\n\nINSERT INTO department (id, name) VALUES\n  (1, '개발팀'), (2, '디자인팀'), (3, '경영지원팀');\n\nINSERT INTO employee (id, name, dept_id, salary, joined_year) VALUES\n  (1, '김하늘', 1, 3200, 2023),\n  (2, '이준호', 1, 4100, 2021),\n  (3, '박서연', 2, 3600, 2022),\n  (4, '최민준', 1, 2900, 2024),\n  (5, '정유진', 2, 3300, 2023),\n  (6, '한지우', 3, 3800, 2020),\n  (7, '오세훈', 3, 2700, 2024),\n  (8, '서지민', 1, 4500, 2019);",
    "sqlExpected": {
      "expectedColumns": [
        "id",
        "name",
        "dept_id",
        "salary",
        "joined_year"
      ],
      "expectedRows": [
        [
          1,
          "김하늘",
          1,
          3200,
          2023
        ],
        [
          2,
          "이준호",
          1,
          4100,
          2021
        ],
        [
          3,
          "박서연",
          2,
          3600,
          2022
        ],
        [
          4,
          "최민준",
          1,
          2900,
          2024
        ],
        [
          5,
          "정유진",
          2,
          3300,
          2023
        ],
        [
          6,
          "한지우",
          3,
          3800,
          2020
        ],
        [
          7,
          "오세훈",
          3,
          2700,
          2024
        ],
        [
          8,
          "서지민",
          1,
          4500,
          2019
        ]
      ],
      "orderMatters": false
    }
  },
  {
    "language": "SQL",
    "title": "조건으로 거르기 (WHERE)",
    "difficulty": "EASY",
    "topic": "sql",
    "description": "연봉(salary)이 3500만원 이상인 직원의 이름(name)만 조회하세요.\n\n힌트: WHERE 절이 \"행을 거르는 조건\"입니다. 이상은 >= 로 씁니다.\n필요한 컬럼(name)만 SELECT 하는 것도 문제의 일부예요 — *를 쓰면 컬럼이 남아서 틀립니다.",
    "starterCode": "-- 연봉 3500 이상 직원의 이름만\nSELECT ",
    "functionName": null,
    "tests": null,
    "setupSql": "CREATE TABLE department (\n  id   INTEGER PRIMARY KEY,   -- 부서 번호\n  name TEXT NOT NULL          -- 부서 이름\n);\n\nCREATE TABLE employee (\n  id          INTEGER PRIMARY KEY,  -- 사번\n  name        TEXT NOT NULL,        -- 이름\n  dept_id     INTEGER NOT NULL,     -- 소속 부서 번호 (department.id)\n  salary      INTEGER NOT NULL,     -- 연봉 (만원)\n  joined_year INTEGER NOT NULL      -- 입사 연도\n);\n\nINSERT INTO department (id, name) VALUES\n  (1, '개발팀'), (2, '디자인팀'), (3, '경영지원팀');\n\nINSERT INTO employee (id, name, dept_id, salary, joined_year) VALUES\n  (1, '김하늘', 1, 3200, 2023),\n  (2, '이준호', 1, 4100, 2021),\n  (3, '박서연', 2, 3600, 2022),\n  (4, '최민준', 1, 2900, 2024),\n  (5, '정유진', 2, 3300, 2023),\n  (6, '한지우', 3, 3800, 2020),\n  (7, '오세훈', 3, 2700, 2024),\n  (8, '서지민', 1, 4500, 2019);",
    "sqlExpected": {
      "expectedColumns": [
        "name"
      ],
      "expectedRows": [
        [
          "이준호"
        ],
        [
          "박서연"
        ],
        [
          "한지우"
        ],
        [
          "서지민"
        ]
      ],
      "orderMatters": false
    }
  },
  {
    "language": "SQL",
    "title": "정렬해서 상위 3명만 (ORDER BY + LIMIT)",
    "difficulty": "NORMAL",
    "topic": "sql",
    "description": "연봉이 높은 순서대로 상위 3명의 이름(name)과 연봉(salary)을 조회하세요.\n\n이 문제는 순서까지 채점합니다 — 연봉이 높은 사람이 첫 줄에 와야 해요.\n\n힌트: ORDER BY salary DESC 가 \"연봉 내림차순 정렬\"입니다.\nLIMIT 3 을 붙이면 앞에서 3행만 가져옵니다. (실무에서 \"톱 N\" 조회의 기본 패턴)",
    "starterCode": "-- 연봉 상위 3명: 이름, 연봉 (높은 순)\nSELECT ",
    "functionName": null,
    "tests": null,
    "setupSql": "CREATE TABLE department (\n  id   INTEGER PRIMARY KEY,   -- 부서 번호\n  name TEXT NOT NULL          -- 부서 이름\n);\n\nCREATE TABLE employee (\n  id          INTEGER PRIMARY KEY,  -- 사번\n  name        TEXT NOT NULL,        -- 이름\n  dept_id     INTEGER NOT NULL,     -- 소속 부서 번호 (department.id)\n  salary      INTEGER NOT NULL,     -- 연봉 (만원)\n  joined_year INTEGER NOT NULL      -- 입사 연도\n);\n\nINSERT INTO department (id, name) VALUES\n  (1, '개발팀'), (2, '디자인팀'), (3, '경영지원팀');\n\nINSERT INTO employee (id, name, dept_id, salary, joined_year) VALUES\n  (1, '김하늘', 1, 3200, 2023),\n  (2, '이준호', 1, 4100, 2021),\n  (3, '박서연', 2, 3600, 2022),\n  (4, '최민준', 1, 2900, 2024),\n  (5, '정유진', 2, 3300, 2023),\n  (6, '한지우', 3, 3800, 2020),\n  (7, '오세훈', 3, 2700, 2024),\n  (8, '서지민', 1, 4500, 2019);",
    "sqlExpected": {
      "expectedColumns": [
        "name",
        "salary"
      ],
      "expectedRows": [
        [
          "서지민",
          4500
        ],
        [
          "이준호",
          4100
        ],
        [
          "한지우",
          3800
        ]
      ],
      "orderMatters": true
    }
  },
  {
    "language": "SQL",
    "title": "부서별로 묶어서 세기 (GROUP BY)",
    "difficulty": "NORMAL",
    "topic": "sql",
    "description": "부서 번호(dept_id)별로 직원이 몇 명인지 조회하세요.\n결과 컬럼: dept_id, 인원 수 — 2개 컬럼이어야 합니다.\n\n힌트: GROUP BY dept_id 는 \"부서 번호가 같은 행끼리 묶어라\"입니다.\n묶고 나면 COUNT(*)로 각 묶음의 행 수를 셀 수 있어요.\nWHERE는 묶기 전에 거르고, 집계 결과로 거르려면 HAVING을 씁니다 — 차이를 기억해 두세요.",
    "starterCode": "-- 부서 번호별 직원 수\nSELECT ",
    "functionName": null,
    "tests": null,
    "setupSql": "CREATE TABLE department (\n  id   INTEGER PRIMARY KEY,   -- 부서 번호\n  name TEXT NOT NULL          -- 부서 이름\n);\n\nCREATE TABLE employee (\n  id          INTEGER PRIMARY KEY,  -- 사번\n  name        TEXT NOT NULL,        -- 이름\n  dept_id     INTEGER NOT NULL,     -- 소속 부서 번호 (department.id)\n  salary      INTEGER NOT NULL,     -- 연봉 (만원)\n  joined_year INTEGER NOT NULL      -- 입사 연도\n);\n\nINSERT INTO department (id, name) VALUES\n  (1, '개발팀'), (2, '디자인팀'), (3, '경영지원팀');\n\nINSERT INTO employee (id, name, dept_id, salary, joined_year) VALUES\n  (1, '김하늘', 1, 3200, 2023),\n  (2, '이준호', 1, 4100, 2021),\n  (3, '박서연', 2, 3600, 2022),\n  (4, '최민준', 1, 2900, 2024),\n  (5, '정유진', 2, 3300, 2023),\n  (6, '한지우', 3, 3800, 2020),\n  (7, '오세훈', 3, 2700, 2024),\n  (8, '서지민', 1, 4500, 2019);",
    "sqlExpected": {
      "expectedColumns": [
        "dept_id",
        "count"
      ],
      "expectedRows": [
        [
          1,
          4
        ],
        [
          2,
          2
        ],
        [
          3,
          2
        ]
      ],
      "orderMatters": false
    }
  },
  {
    "language": "SQL",
    "title": "두 테이블 이어 붙이기 (JOIN)",
    "difficulty": "HARD",
    "topic": "sql",
    "description": "모든 직원의 이름과 \"부서 이름\"을 나란히 조회하세요.\n결과 컬럼: 직원 이름, 부서 이름 — 2개 컬럼이어야 합니다.\n\n부서 이름은 employee에 없고 department에 있습니다. 두 테이블을 이어야 해요.\n\n힌트: JOIN department ON employee.dept_id = department.id\n두 테이블에 같은 이름의 컬럼(name)이 있으니 employee.name 처럼 테이블을 붙여 구분하세요.\n테이블 이름이 길면 FROM employee e 처럼 별칭(alias)을 쓸 수 있습니다.",
    "starterCode": "-- 직원 이름 + 부서 이름\nSELECT ",
    "functionName": null,
    "tests": null,
    "setupSql": "CREATE TABLE department (\n  id   INTEGER PRIMARY KEY,   -- 부서 번호\n  name TEXT NOT NULL          -- 부서 이름\n);\n\nCREATE TABLE employee (\n  id          INTEGER PRIMARY KEY,  -- 사번\n  name        TEXT NOT NULL,        -- 이름\n  dept_id     INTEGER NOT NULL,     -- 소속 부서 번호 (department.id)\n  salary      INTEGER NOT NULL,     -- 연봉 (만원)\n  joined_year INTEGER NOT NULL      -- 입사 연도\n);\n\nINSERT INTO department (id, name) VALUES\n  (1, '개발팀'), (2, '디자인팀'), (3, '경영지원팀');\n\nINSERT INTO employee (id, name, dept_id, salary, joined_year) VALUES\n  (1, '김하늘', 1, 3200, 2023),\n  (2, '이준호', 1, 4100, 2021),\n  (3, '박서연', 2, 3600, 2022),\n  (4, '최민준', 1, 2900, 2024),\n  (5, '정유진', 2, 3300, 2023),\n  (6, '한지우', 3, 3800, 2020),\n  (7, '오세훈', 3, 2700, 2024),\n  (8, '서지민', 1, 4500, 2019);",
    "sqlExpected": {
      "expectedColumns": [
        "name",
        "name"
      ],
      "expectedRows": [
        [
          "김하늘",
          "개발팀"
        ],
        [
          "이준호",
          "개발팀"
        ],
        [
          "박서연",
          "디자인팀"
        ],
        [
          "최민준",
          "개발팀"
        ],
        [
          "정유진",
          "디자인팀"
        ],
        [
          "한지우",
          "경영지원팀"
        ],
        [
          "오세훈",
          "경영지원팀"
        ],
        [
          "서지민",
          "개발팀"
        ]
      ],
      "orderMatters": false
    }
  }
]
