(개인정보 관련 논의를 사전에 방지하기 위해 다음 사항을 명시합니다. 우리는 유료 회원들을 위한 사설 Discourse를 운영하고 있으며, 회원들은 서비스 제공 목적으로 자신의 개인 정보를 사용할 수 있도록 개별적으로 동의했습니다. 우리는 자동화된 방식으로 상호 운용되지 않는 시스템을 사용하고 있으며, 두 가지 다른 시스템의 사용자를 수동으로 연결하기 위해 이메일을 사용하고 있습니다.)
category_id = <number> 필터를 아예 제거하면 됩니다. 그러면 쿼리는 다음과 같이 보입니다:
SELECT
cu.*,
ue.email
FROM category_users cu
JOIN user_emails ue
ON ue.user_id = cu.user_id
WHERE ue.primary = true
Data Explorer는 카테고리 이름을 표시해 주지만, 결과를 내보낼 때 해당 이름은 표시되지 않습니다. 이 점이 문제가 된다면, 카테고리 이름을 컬럼으로 명시적으로 추가할 수 있습니다. 예를 들어 다음과 같이요:
SELECT
c.name,
cu.*,
ue.email
FROM category_users cu
JOIN user_emails ue
ON ue.user_id = cu.user_id
JOIN categories c
ON cu.category_id = c.id
WHERE ue.primary = true
ORDER BY c.name
정확히 말하면 그렇지 않습니다. @simon님의 쿼리를 약간 다시 포맷하면 더 명확해질 수 있습니다:
SELECT
cu.*,
ue.email
FROM category_users cu
JOIN user_emails ue ON ue.user_id = cu.user_id
WHERE (category_id = '10' AND ue.primary = true)
category_id와 ue.primary 조건은 모두 AND로 연결된 WHERE 절의 일부입니다. 조건 중 하나를 제거하면 AND는 제거되지만 WHERE 절은 유지됩니다.
대부분의 간단한 SQL 쿼리는 다음과 같은 형태를 따릅니다:
SELECT <원하는 항목>
FROM <테이블>
WHERE <필터 조건>
WHERE 절을 아예 생략할 수도 있지만, 그렇게 하면 지정된 테이블의 모든 행을 반환받게 됩니다.
다음은 원래 쿼리(다시 포맷된 형태)입니다:
SELECT *
FROM category_users
WHERE category_id = '10'
"SELECT *"는 포함된 모든 테이블의 모든 컬럼을 쿼리가 반환하도록 하겠다는 의미입니다.
"FROM category_users"는 쿼리를 실행할 테이블을 나타냅니다. category_users 테이블에는 다음과 같은 행이 포함되어 있습니다:
id
category_id
user_id
notification_level
1
1
1
3
2
1
2
3
3
3
1
3
category_id와 user_id는 다른 테이블(이 경우 categories 및 users 테이블)의 행을 가리키기 때문에 **외래 키(foreign keys)**라고 불립니다. 따라서 위의 3개 행은 ID가 1인 사용자가 카테고리 1과 3을, ID가 2인 사용자가 카테고리 1을 보고 있다는 것을 의미합니다. notification_level은 사용자가 Watching(관심), Watching First Post(첫 게시물 관심) 또는 Tracking(추적) 상태인지 나타냅니다.
"WHERE category_id = '10'"은 category_id 컬럼의 값이 10인 행에만 관심이 있다는 의미입니다. 이 줄이 없다면 category_users 테이블의 모든 행을 받게 됩니다.
@simon님은 사용자의 이메일 주소를 추가한 새로운 버전을 제공했습니다:
이 쿼리는 원래 쿼리에서 몇 가지 변경 사항을 포함하고 있으며, 그 이유는 두 가지입니다: 이메일 주소는 다른 테이블(user_emails 테이블)에 저장되어 있고, 사용자는 여러 개의 이메일 주소를 가질 수 있기 때문입니다.
SELECT 절에서:
"cu.*"는 cu 테이블의 모든 컬럼을 의미합니다.
"ue.email"는 ue 테이블의 email 컬럼을 의미합니다.
FROM 절에서:
category_users 테이블에는 이제 별칭 "cu"가 부여되었습니다. 이는 테이블을 여러 번 참조해야 할 때 타이핑을 줄여줍니다.
user_emails 테이블과 JOIN을 수행했으며, 이 테이블에는 ue라는 별칭을 부여했습니다.
SQL에서 두 테이블을 JOIN할 때는 일반적으로 데이터베이스에 **조인 조건(join condition)**을 알려야 합니다. 그렇게 하지 않으면 데이터베이스가 각 테이블의 어떤 값이 서로 일치해야 하는지 알 수 없으므로, 두 테이블의 모든 가능한 행 조합이 생성됩니다. 다음과 같은 쿼리를 작성한다면:
SELECT *
FROM category_users
JOIN user_emails
…위 예시 데이터를 기준으로 9개의 행을 받게 됩니다: category_users의 첫 번째 행이 user_emails의 각 행과 매칭되어 3번 반환되고, 이어서 두 번째category_users 행이 3번, 마지막으로 세 번째category_users 행이 3번 반환됩니다.
조인 조건은 일반적으로 두 테이블의 어떤 컬럼이 동일한 값을 나타내는지 데이터베이스에 알려줍니다. 이 경우 category_users.user_id 컬럼과 user_emails.user_id 컬럼은 모두 동일한 값을 나타냅니다. JOIN user_emails ue 뒤에 ON ue.user_id = cu.user_id를 작성함으로써, 데이터베이스가 user_emails 행을 적절한 category_users 행과 매칭하도록 지시합니다.
JOIN 조건이 있어도 ID가 1인 사용자의 경우 여전히 4개의 행을 받게 됩니다. 이는 해당 사용자가 2개의 카테고리를 보고 있고 2개의 이메일 주소를 가지고 있기 때문에, 각 조합에 대해 행이 하나씩 반환되기 때문입니다. 따라서 @simon님은 쿼리가 사용자의 주 이메일 주소가 포함된 행만 반환하도록 WHERE 절에 추가 조건을 넣었습니다. 이 조건은 이미 존재하는 조건(카테고리 ID 제한)에 추가된 것입니다 - 반환되는 행은 category_id = '10'이고ue.primary = true여야 합니다.
그 후, 검색 범위를 단일 카테고리로 제한하지 않으려고 하셨기 때문에 단순히 category_id 필터를 제거하면 되었습니다. 여전히 주 이메일 주소만 반환하고 싶으므로 WHERE 절 전체를 제거하면 안 됩니다. 다시 말해, 필터 조건이 다음과 같이 변경되었습니다: