2013-09-21 2 views
-2

Этот запросSUM (DISTINCT (колонка)) дает неверные результаты при определенных условиях

SELECT u.username, 
SUM(p.likes) AS likePoints1, 
SUM(p2.likes)*2 AS likePoints2 
FROM users as u 
LEFT JOIN (SELECT recommendedByUserId as rid, id as ruid from users WHERE created >= DATE('2013-09-16') AND created <= DATE('2013-09-30')) AS r ON r.rid = u.id 
LEFT JOIN (SELECT * FROM posts WHERE created >= DATE('2013-09-16') AND created <= DATE('2013-09-30')) AS p ON p.author_id = ruid 
LEFT JOIN (SELECT * FROM posts WHERE created >= DATE('2013-09-16') AND created <= DATE('2013-09-30')) AS p2 ON p2.author_id = u.id 
GROUP BY u.id 

дает неправильные результаты на колонке "likePoints2" Хотя это

SELECT u.username, 
SUM(p2.likes)*2 AS likePoints2 
FROM users as u 
LEFT JOIN (SELECT * FROM posts WHERE created >= DATE('2013-09-16') AND created <= DATE('2013-09-30')) AS p2 ON p2.author_id = u.id 
GROUP BY u.id 

совершенно правильно.

Проблема в том, что мне нужно подвести итог всех сообщений.likes на posts.author_id = current u.id в течение заданного диапазона дат.

Буду признателен за любые вводные данные!

ТЕСТ-ДАННЫХ

ПОЛЬЗОВАТЕЛИ

id | recommendedByUserId 
1 | 3 
2 | 3 
3 | NULL 
4 | 1 

ПОСТЫ

author_id | likes 
1   | 5 
3   | 2 
4   | 1 

Таким образом, в приведенном выше примере, результат должен быть:

userid | recommPoints | likePoints1 | likePoints2 
1  | 10   | 1   | 10 
2  | NULL   | NULL  | NULL 
3  | 20   | 5   | 4 
4  | NULL   | NULL  | 2 
+0

Что неправильно результаты вы получаете? –

+0

Вы попробовали «правое внешнее соединение?»? Вы также можете напрямую присоединиться к таблицам, используя предложение where этих подзапросов как дополнительное условие для предиката соединения (возможное усиление производительности). – Sam

+0

@GoatCO SUM слишком высок, не могу сказать, откуда он. –

ответ

2

Основная проблема заключается в том, что каждое соединение добавляет несколько строк для связанных значений. Таким образом, вы в конечном итоге считаете вещи несколько раз. Общий способ решить эту задачу, чтобы каждая отдельная группа группировала отдельный поднабор. Вы можете оставить его частью основного выбора.

Хорошим способом диагностики таких проблем является удаление группы и просмотр базового набора данных. Используйте предложение where, чтобы ограничить известный случай, который не работает.

Select 
    u.username, 
    p1.likePoints1, 
    p1.recommPoints, 
    Sum(p2.likes) * 2 As likePoints2 -- assume the *2 is part of the algorithm 
From 
    users u 
     Left Outer Join (
      Select 
       r.recommendedByUserId rid, 
       Sum(p.likes) AS likePoints1, 
       Count(Distinct r.id) * 10 As recommPoints 
      From 
       users r 
        Left Outer Join 
       posts p 
        On r.id = p.author_id And 
         p.created >= Date('2013-09-16') And 
         p.created <= Date('2013-09-30') 
      Where 
       r.created >= Date('2013-09-16') And 
       r.created <= Date('2013-09-30') 
      Group By 
       r.recommendedByUserId 
    ) p1 
     on u.id = p1.rid 
     Left Outer Join 
    posts p2 
     On p2.author_id = u.id And 
      p2.created >= Date('2013-09-16') And 
      p2.created <= Date('2013-09-30') 
Group By 
    u.username, 
    p1.likePoints1, 
    p1.recommPoints 

урезывание Example Fiddle

+0

Это выглядит хорошо, но (я оставил это в своем вопросе) Мне нужен столбец «ruid» для «COUNT (DISTINCT ruid) * 10 AS recommPoints» –

+0

Я пробовал, но это намного превосходит мои возможности в SQL. Я должен признать :( –

+0

понял, я думаю ... я не как свалка, как предполагалось;) ... или я ... не работает. Я просто добавил «r.id как ruid» прямо под «r.recommendedByUserId rid» и «COUNT (DISTINCT ruid) * 10 AS recommPoints» сверху, не выполняет работу :( –

Смежные вопросы