简体   繁体   English

SQL select 和排序依据(第二个表内的相关记录数)减去(第二个表内相关记录数的条件)

[英]SQL select and order by (count of related records inside a second table) subtracted by (count of related records inside second table with condition)

I am trying to SELECT every record in a table one ORDER ed BY the COUNT of records inside a second table that store the related primary key value and WHERE 'positive' is true, subtracted by the COUNT of records inside the second table that store the related primary key value and WHERE 'positive' is false.我正在尝试SELECT表中的每条记录一个ORDER BY存储相关主键值的第二个表内的记录数,并且WHERE ' positive ' 为真,减去第二个表内存储的记录数相关的主键值和WHERE 'positive' 为 false。

Here is my database structure这是我的数据库结构

Table 1表格1

id ID data数据
0 0 zero
1 1个 one
2 2个 two
3 3个 three

Table 2表 2

id ID related_tableone_id related_tableone_id positive积极的
0 0 1 1个 0 0
1 1个 2 2个 1 1个
2 2个 2 2个 0 0
3 3个 2 2个 1 1个
4 4个 3 3个 1 1个
5 5个 3 3个 1 1个

Here is what I am trying to get这是我想要得到的

id ID data数据 subtracted_counts (i dont need this but these values are what the records should be ordered by) subtracted_counts(我不需要这个,但这些值是记录的排序依据)
3 3个 three 2 2个
2 2个 two 1 1个
0 0 zero 0 0
1 1个 one -1 -1

For better understanding on what i want to achieve:为了更好地理解我想要实现的目标:
This database structure can be compared with a voting system , where Table 1 are entities that can be voted up or voted down .可以将此数据库结构与投票系统进行比较,其中表 1 是可以投票赞成投票反对的实体。
In this case, Table 2 would store the votes with positive=true for an upvote and positive=false for a downvote .在这种情况下,表 2 将存储positive=true表示赞成票positive=false表示反对票的选票
The goal is to get all entities ORDER ed BY their summarized vote value .目标是让所有实体按其汇总的投票值排序
(Within a single query) (在单个查询中)

My research我的研究

I found this post SQL - How To Order Using Count From Another Table , tho there is no subtraction logic我发现这篇文章SQL - How To Order Using Count From Another Table ,虽然没有减法逻辑

I tried this query我试过这个查询

SELECT 
    tableone.*, 
    COUNT(related_tableone_id) - COUNT(negative_related_tableone_id) AS subtracted_count
FROM 
    tableone 
LEFT JOIN 
    (SELECT related_tableone_id 
     FROM tabletwo 
     WHERE positive = true) AS positives ON tableone.id = positives.related_tableone_id
LEFT JOIN 
    (SELECT related_tableone_id AS negative_related_tableone_id 
     FROM tabletwo 
     WHERE positive = false) AS negatives ON tableone.id = negatives.negative_related_tableone_id
GROUP BY 
    tableone.id
ORDER BY 
    subtracted_count DESC;

But it doesn't subtract the counts right for some reason and there is probably a more clear solution但是由于某种原因它并没有正确地减去计数,并且可能有一个更清晰的解决方案

A single subquery can count both upvotes and downvotes, using conditional aggregation.使用条件聚合,单个子查询可以计算赞成票和反对票。 I would use a lateral join to do the computation:我会使用横向连接来进行计算:

select t1.*, t2.*
from tableone t1
cross join lateral (
    select 
        sum(case when t2.positive = true  then 1 else 0 end) upvotes,
        sum(case when t2.positive = false then 1 else 0 end) downvotes
    from tabletwo t2
    where t2.related_tableone_id = t1.id
) t2
order by t2.upvotes - t2.downvotes desc, t1.id

Depending on your database, the lateral join might be introduced by cross apply instead (eg in Oracle or SQL Server).根据您的数据库,横向连接可能由cross apply引入(例如在 Oracle 或 SQL 服务器中)。

Use a LEFT join of Table1 to Table2 and conditional aggregation in the ORDER BY clause:ORDER BY子句中使用Table1Table2LEFT连接和条件聚合:

SELECT t1.id, t1.data       
FROM Table1 t1 LEFT JOIN Table2 t2
ON t2.related_tableone_id = t1.id
GROUP BY t1.id
ORDER BY SUM(CASE t2.positive WHEN true THEN 1 WHEN false THEN -1 ELSE 0 END) DESC;

or, a correlated subquery in the ORDER BY clause (which may perform better):或者, ORDER BY子句中的相关子查询(可能表现更好):

SELECT t1.*
FROM Table1 t1
ORDER BY (
  SELECT COALESCE(SUM(CASE t2.positive WHEN true THEN 1 WHEN false THEN -1 END) , 0)
  FROM Table2 t2 
  WHERE t2.related_tableone_id = t1.id
) DESC;

See the demo (works in MySql, Postgresql and SQLite).请参阅演示(适用于 MySql、Postgresql 和 SQLite)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM