2016-06-15 3 views
0

alert, user_to_alert 및 user_device 테이블이 3 개 있습니다. 장치 테이블은 토큰 목록을 보유하고 user_id 필드를 포함합니다.가입 된 상관 하위 쿼리

user_to_alert 테이블에는 사용자가 경고를 읽을 때 기록이 보관됩니다. 적절한 alert_id/user_id 콤보에 대한 레코드가 없으면 사용자가 경고를 읽지 않았 음을 의미합니다. 또한 alert_read 열은 0 일 수 있습니다 (사용자가 읽은 후 경고를 읽지 않은 것으로 표시 한 경우).

장치 토큰 목록을로드하는 쿼리가 있는데 읽지 않은 경고 수가 포함되도록이 토큰을 확장해야합니다. 이것은 내가

SELECT d.*, (
SELECT COUNT(*) FROM `alert` AS a 
LEFT JOIN `user_to_alert` AS uta ON 
(uta.`alert_id` = a.`alert_id` AND uta.`user_id` = d.`user_id`) 
WHERE uta.`alert_read` = 0 OR uta.`alert_read` IS NULL) AS user_badge_number 
FROM `user_device` AS d 
WHERE d.`device_type` = 'iOS' AND d.`device_active` = 1 
GROUP BY d.`device_token` 

이 쿼리와 함께 왔어요 질의 것은 내가 설정을했습니다 나에게 오류 #1054 - Unknown column 'd.user_id' in 'on clause'

을 제공 스키마 및 쿼리와의 SQLFiddle : http://sqlfiddle.com/#!9/ee653/2

내 서브를 실행하는 경우 별도로 쿼리하고 유효한 user_id 대신 d.user_id를 사용하면 예상되는 결과를 얻습니다 (예 : user_id 10의 경우 3). 이 문제는 내가 d.user_id 열을 참조하고 있음을 의미한다고 가정합니다. 나는 d.user_id가 아직 유효한 컬럼이 아니기 때문에 MySQL이 서브 쿼리를 먼저 수행하려고 시도하고 있다고 생각한다. 그것은 단지 추측입니다.

ON 절의 부분을 uta.user_id = d.user_id WHERE 절로 이동했지만 모든 행에 user_badge_number 열에 0을 부여했습니다.

Google에서이 문제와 관련된 것을 찾는 데 문제가 있습니다. 상관 관계가있는 부질의에 대해 찾은 모든 것은 여분의 데이터를 검색하는 대신 ON 또는 WHERE 절에서 사용하는 것 같습니다.

이것은 PHP 스크립트를 통해 실행되므로 PHP 스크립트의 결과 루프 내에서 하위 쿼리를 단독으로 실행할 수 있음을 알고 있습니다. 분명히, 나는 오히려 더 효율적 일 것이기 때문에 한 가지 질문으로 그것을하는 방법을 이해할 것입니다. 당신이 언급 한 바와 같이

답변

0

를 사용하는 하드되지를 시도합니다. 읽지 않은 수를 얻기 위해 총 경고에서 해당 뺄 수 있습니다

SELECT d.*, 
    (SELECT COUNT(*) FROM `alert`) - 
    (SELECT COUNT(*) FROM `user_to_alert` 
     WHERE `user_id` = d.`user_id` AND `alert_read` = 1) 
FROM `user_device` AS d 
WHERE d.`device_active` AND d.`device_type` = 'iOS'; 

을하지만 인 디자인에 문제가 참고 장치 또는 사용자 6 개월 지금부터 추가되면, 모든 경고 과거는 새 기기에서 읽지 않은 상태로 표시됩니다. 장치가 새로운 사용자에게 재 할당되거나 기존 사용자가 장치를 전환하는 경우에도 비슷한 문제가 있습니다 (사용자 당 또는 사용자 당 을 계산하지 않음 여부에 따라).

이 문제를 해결하려면 사용자 또는 장치가 추가되었을 때 특정 날짜 범위로 쿼리를 제한 할 수 있습니다. 그러나 장치를 재 할당하는 경우 사용할 날짜가 명확하지 않습니다.) 더 간단한 대답은 다음과 같습니다. 각 경고가 작성되면 user_to_alert에 행을 삽입하십시오.새로운 기능을 추가 할 수 있습니다

  • 사용자 또는 장치에 대한 읽지 않은 행의 수를 계산하기 쉬운
  • 새로운 장치/사용자가 상속하지 않는 오래된 경고
  • : 이것은 몇 가지 장점이있을 것입니다 경고를 그 일부 사용자/장치에만 전달됩니다.
+0

나는 장치가 아닌 사용자를 기반으로 경고 읽기를 추적하고 있습니다. 사용자가 두 개 이상의 기기를 사용하는 경우 읽지 않은 횟수는 모든 기기에서 동일합니다. 알리미를 발송 한 후에 작성한 사용자에 대해서는 좋은 지적이 있습니다. 전체 계정 수를 사용자 계정을 만든 후 보낸 경고만으로 제한함으로써이 문제를 피할 수있었습니다. 내 답변을 제거하고 쿼리 자체 내에서 뺄셈을 사용하면 조금 더 나아질 것이므로이를 받아 들일 것입니다. – kinadian

+0

내가 제기 한 문제를 해결하기 위해 날짜 범위를 사용하는 것이 좋은 점. 나는 그 제안을 포함하도록 나의 대답을 편집했다. – Bampfer

+0

FWIW 당신의 삭제 된 대답은 나에게 뺄셈을 할 수있는 아이디어를주었습니다. 첫 번째 초안은 읽지 않은 항목의 수를 계산하기 위해 CROSS JOIN을 사용했습니다. 뺄셈은 훨씬 간단했다. – Bampfer

0

그것은 상관 하위 쿼리의 범위 문제가있어, 읽은 경고의 수를 계산, 테이블 이름

SELECT d.*, (
    SELECT COUNT(*) FROM `alert` AS a 
    LEFT JOIN `user_to_alert` AS uta ON 
    (uta.`alert_id` = a.`alert_id`) 
    WHERE uta.`user_id` = d.`user_id` AND 
      (uta.`alert_read` = 0 OR uta.`alert_read` IS NULL)) 
      AS user_badge_number 
FROM `user_device` AS d 
WHERE d.`device_type` = 'iOS' AND d.`device_active` = 1 
GROUP BY d.`device_token` 
+0

제안 된 쿼리를 변경하면 오류가 해결되지만 user_badge_number 값이 올바르지 않습니다. 나는 SQLFiddle (http://sqlfiddle.com/#!9/ee653/19)을 조정했고 두 결과 모두 3을 제공합니다. 그것은 사용자 # 10에 대해 3을, 사용자 # 11에 대해 7을 제공해야합니다. – kinadian

+0

@kinadian, 업데이트 된 쿼리 http://sqlfiddle.com/#!9/82be5/4를 확인할 수 있습니까? – Kld

+0

@Kid, 올바른 결과를주는 것 같지 않지만 이유를 알 수 없습니다. 내가 그것을 읽을 때, 그것은 작동해야하지만 그것은 읽지 않은 카운트 대신 읽기 카운트를주는 것으로 보인다. – kinadian