withCount () - получить разницу в 2 счета - PullRequest
1 голос
/ 08 января 2020

У меня есть таблица со столбцом is_up_vote = true|false

Я пытаюсь написать запрос, используя withCount(), поэтому он возвращает мне сумму истинных и ложных значений.

select COUNT(is_up_vote) from comment_votes WHERE is_up_vote = true возвращает 17

select COUNT(is_up_vote) from comment_votes WHERE is_up_vote = false возвращает 15

Однако я не мог понять, как получить различные из них, поэтому итоговое значение возвращает 2.

То, что я пробовал, это:

Model::withCount(['votes' => function($q) {
 $q->selectRaw(
    '(SUM (COUNT(is_up_vote) WHERE is_up_vote = true) - (COUNT(is_up_vote) WHERE is_up_vote = false) )'
 );
}]);

Но это возвращает 17 + 15 = 32

без SUM(), это также возвращает 32.

$q->selectRaw(
   '( (COUNT(is_up_vote) WHERE is_up_vote = true) - (COUNT(is_up_vote) WHERE is_up_vote = false) )'
);

Что я делаю что-то не так?

Редактировать :

Если я попробую одну сторону, она игнорирует где и все еще возвращает 32, поэтому не вызывается где (где это делает в sql)

return $query->withCount(['votes' => function($q) {
   $q->selectRaw('(COUNT(is_up_vote) WHERE is_up_vote = true)');
}]);

запрос продолжения маунала возвращает 17:

select COUNT(is_up_vote) from comment_votes WHERE is_up_vote = true

Редактировать 2:

$query->withCount([
    'votes as up_votes_count' => function($q) {
        $q->where('is_up_vote', true);
    },
    'votes as down_votes_count' => function($q) {
        $q->where('is_up_vote', false);
    },
]);

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

Ответы [ 4 ]

0 голосов
/ 09 января 2020

Согласно инструкциям, которые комментирует @Jefferson Pessanha, достаточно просто использовать Model::selectRaw('(abs(2 * sum(is_up_vote) - count(*)))')->get();

0 голосов
/ 09 января 2020

withCount может не справиться с этим делом. как насчет использования addSelect для подсчета голосов.

return Model::addSelect(['votes_count' => Vote::selectRaw('( (COUNT(is_up_vote) WHERE is_up_vote = true) - (COUNT(is_up_vote) WHERE is_up_vote = false) )')
    ->whereColumn('parent_id', 'parents.id')
])->get();

Я не знаю, будет ли работать подзапрос. Но вы знаете эту идею.

0 голосов
/ 09 января 2020
create table comment_votes
(
    is_up_vote tinyint(1) default 1 null
);
insert into comment_votes values (true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true);
insert into comment_votes values (false),(false),(false),(false),(false),(false),(false),(false),(false),(false),(false),(false),(false),(false),(false);

select COUNT(is_up_vote) from comment_votes WHERE is_up_vote = true; возвращает 17 select COUNT(is_up_vote) from comment_votes WHERE is_up_vote = false; возвращает 15 select (abs(2 * sum(is_up_vote) - count(*))) from comment_votes; возвращает 2

Объясните:

trueValues ​​+ falseValues ​​= всего falseValues ​​= всего - trueValues trueValues ​​- falseValues ​​= x trueValues ​​- (всего - trueValues) = x 2 * trueValues ​​- всего = х

trueValues ​​= sum (is_up_vote) [учитываются только истины, сохраненные как 1] итого = кол-во (*)

Функция Abs предназначена для преобразования результата в положительное значение в случае отрицательного значения

Разве это не правильно?

0 голосов
/ 08 января 2020

Попробуйте это.

select 
sum( if(is_up_vote= true, 1, 0) ) as uptrue, 
sum( if(is_up_vote= false, 1, 0) ) as upfalse,
sum( if(is_up_vote= true, 1, -1) ) as updiff
from comment_votes

Редактировать: 1

Вместо проверки, является ли это истиной или ложью, попробуйте это.

select 
sum( if(is_up_vote, 1, 0) ) as uptrue, 
sum( if(is_up_vote, 0, 1) ) as upfalse,
sum( if(is_up_vote, 1, -1) ) as updiff
from comment_votes
...