update select_related raw queryset query example sql django django-queryset

sql - raw - select_related django example



Django annotate() varias veces causa respuestas incorrectas (2)

Gracias por tu comentario. Eso no funcionó del todo, pero me guió en la dirección correcta. Finalmente pude resolver esto agregando distintas a las llamadas Count ():

Count(''tourcomment'', distinct=True)

Django tiene la gran nueva función annotate () para querysets. Sin embargo, no puedo hacer que funcione correctamente para múltiples anotaciones en un solo conjunto de consultas.

Por ejemplo,

tour_list = Tour.objects.all().annotate( Count(''tourcomment'') ).annotate( Count(''history'') )

Un tour puede contener múltiples entradas de tourcomment e historial. Estoy intentando saber cuántos comentarios y entradas de historial existen para esta gira. La resultante

history__count and tourcomment__count

Los valores serán incorrectos. Si solo hay una llamada annotate (), el valor será correcto.

Parece que hay algún tipo de efecto multiplicativo que proviene de las dos LEFT OUTER JOIN . Por ejemplo, si un recorrido tiene 3 historias y 3 comentarios, 9 será el valor de conteo para ambos. 12 historias + 1 comentario = 12 para ambos valores. 1 historial + 0 comentario = 1 historial, 0 comentarios (este sucede para devolver los valores correctos).

La llamada SQL resultante es:

SELECT `testapp_tour`.`id`, `testapp_tour`.`operator_id`, `testapp_tour`.`name`, `testapp_tour`.`region_id`, `testapp_tour`.`description`, `testapp_tour`.`net_price`, `testapp_tour`.`sales_price`, `testapp_tour`.`enabled`, `testapp_tour`.`num_views`, `testapp_tour`.`create_date`, `testapp_tour`.`modify_date`, `testapp_tour`.`image1`, `testapp_tour`.`image2`, `testapp_tour`.`image3`, `testapp_tour`.`image4`, `testapp_tour`.`notes`, `testapp_tour`.`pickup_time`, `testapp_tour`.`dropoff_time`, COUNT(`testapp_tourcomment`.`id`) AS `tourcomment__count`, COUNT(`testapp_history`.`id`) AS `history__count` FROM `testapp_tour` LEFT OUTER JOIN `testapp_tourcomment` ON (`testapp_tour`.`id` = `testapp_tourcomment`.`tour_id`) LEFT OUTER JOIN `testapp_history` ON (`testapp_tour`.`id` = `testapp_history`.`tour_id`) GROUP BY `testapp_tour`.`id` ORDER BY `testapp_tour`.`name` ASC

He intentado combinar los resultados de dos consultas que contienen una sola llamada para anotar (), pero no funciona bien ... Realmente no se puede garantizar que el orden sea el mismo. y parece demasiado complicado y desordenado, así que he estado buscando algo mejor ...

tour_list = Tour.objects.all().filter(operator__user__exact = request.user ).filter(enabled__exact = True).annotate( Count(''tourcomment'') ) tour_list_historycount = Tour.objects.all().filter( enabled__exact = True ).annotate( Count(''history'') ) for i,o in enumerate(tour_list): o.history__count = tour_list_historycount[i].history__count

Gracias por cualquier ayuda. Stackoverflow ha salvado mi trasero en el pasado con muchas preguntas ya contestadas, pero aún no he podido encontrar una respuesta a esta.


No puedo garantizar que esto solucione su problema, pero intente .order_by() a su llamada. Es decir:

tour_list = Tour.objects.all().annotate(Count(''tourcomment'')).annotate(Count(''history'')).order_by()

La razón de esto es que django necesita seleccionar todos los campos en la cláusula ORDER BY, lo que hace que se seleccionen resultados idénticos. Al .order_by() , está eliminando por completo la cláusula ORDER BY, lo que evita que esto suceda. Consulte la documentación de agregación para obtener más información sobre este problema.