Php 按两个字段的计数之和排序

Php 按两个字段的计数之和排序,php,mysql,group-by,sql-order-by,Php,Mysql,Group By,Sql Order By,好的,我这里有一个有趣的问题。我有两张桌子,小费和选票。提示如下: tip_id, challenge_id, user_id, ip_address, tip_date, tip_text tip_id, ip_address, vote_date, vote up | down | rating | tip_id | tip_date | user_id | tip_text --------------------------------------------------------

好的,我这里有一个有趣的问题。我有两张桌子,小费和选票。提示如下:

tip_id, challenge_id, user_id, ip_address, tip_date, tip_text
tip_id, ip_address, vote_date, vote
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
4  | 1    | 3      | 1      | 87654321 | 2       | "this is also a tip"
SELECT v.up, v.down, (v.up - v.down) AS rating, t.tip_id, t.tip_date, t.user_id, t.tip_text
FROM tips AS t
INNER JOIN votes AS v
ON t.tip_id = v.tip_id
WHERE challenge_id=1
ORDER BY rating DESC;
投票结果如下:

tip_id, challenge_id, user_id, ip_address, tip_date, tip_text
tip_id, ip_address, vote_date, vote
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
4  | 1    | 3      | 1      | 87654321 | 2       | "this is also a tip"
SELECT v.up, v.down, (v.up - v.down) AS rating, t.tip_id, t.tip_date, t.user_id, t.tip_text
FROM tips AS t
INNER JOIN votes AS v
ON t.tip_id = v.tip_id
WHERE challenge_id=1
ORDER BY rating DESC;
用户可以发布挑战提示,然后其他用户可以向上或向下拇指投票。投票中的投票字段是布尔值,0表示拇指朝下,1表示拇指朝上。挑战可以有很多技巧

我一直在绞尽脑汁,但我就是无法让它发挥作用。我需要一个查询,可以获得特定小费的上下票数,这两个数字的差值(因此,如果有2个上票数和1个下票数,差值将为1)作为评分,以及小费表中的小费数据,然后首先用最高评分对其进行排序。假设我们有两个提示,a和b:

a:3向上,2向下(差异:1) b:4向上,1向下(差异:3)

在这种情况下,b会排在第一位,因为它的评级比a高,上升和下降的票数相差较大

例如,假设我有一个id为1的提示,有4张赞成票和2张反对票,这意味着相差2,这个提示链接到挑战id 5,我的回报可能如下所示:

tip_id, challenge_id, user_id, ip_address, tip_date, tip_text
tip_id, ip_address, vote_date, vote
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
4  | 1    | 3      | 1      | 87654321 | 2       | "this is also a tip"
SELECT v.up, v.down, (v.up - v.down) AS rating, t.tip_id, t.tip_date, t.user_id, t.tip_text
FROM tips AS t
INNER JOIN votes AS v
ON t.tip_id = v.tip_id
WHERE challenge_id=1
ORDER BY rating DESC;
现在,我已经能够做到这一点了,但我遇到的问题是,如果一个挑战有多个提示,那么我会得到多行。假设挑战id 5有两个提示,那么我应该得到如下结果:

tip_id, challenge_id, user_id, ip_address, tip_date, tip_text
tip_id, ip_address, vote_date, vote
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
4  | 1    | 3      | 1      | 87654321 | 2       | "this is also a tip"
SELECT v.up, v.down, (v.up - v.down) AS rating, t.tip_id, t.tip_date, t.user_id, t.tip_text
FROM tips AS t
INNER JOIN votes AS v
ON t.tip_id = v.tip_id
WHERE challenge_id=1
ORDER BY rating DESC;
每个提示在结果中都有自己的行。现在发生的事情是,我得到了一行,上下值是该挑战的上下投票总数,而不是小费。因此,使用上面的第二个示例,而不是两个单独的行,我将得到一行up的值为7,down的值为3,这是针对该挑战的所有提示的up和down投票总数

我确信这将涉及连接、排序和分组,但我不关心查询有多复杂,我只是不想在PHP中进行。最后,我希望为查询提供一个质询ID,并让它获得X行,其中X是该质询ID的提示数,每行仅包含该提示ID的计数

任何帮助都将不胜感激,因为我已经没有头发可以拔了。不幸的是,这是我的项目的定义点,更高级别的提示需要在列表中显示得更高

编辑:这是我当前的、几乎可以工作的查询。睡了一个好觉后,我对它做了一些调整,使它基本正常工作,但仍有一个问题我无法解释:

SELECT
  COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END) AS up,
  COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END) AS down,
  (COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END)) AS rating,
  T.*
  FROM votes V, tips T
  WHERE T.challenge_id = 10
  GROUP BY V.tip_id
  ORDER BY rating DESC

这会得到我所需要的一切,所有提示和特定挑战的投票,每个提示都有一个新行(而不是像我以前得到的那样,总计数)。问题是,我的上下票数和评级都是应该的两倍。因此,如果我有一个tip,它有3张赞成票和1张反对票,因此评级为2,那么这个查询将显示我有6张赞成票和2张反对票,评级为4。我想我可以简单地用PHP将这个数字除以2,但这并不能解决这个问题,它只是一个绷带。有人知道为什么我的电话号码是我应该得到的两倍吗?我会继续搞乱它,也许尝试左键连接,希望我能找到答案,但如果能有更多的眼睛就好了。

像这样的东西怎么样:

tip_id, challenge_id, user_id, ip_address, tip_date, tip_text
tip_id, ip_address, vote_date, vote
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
4  | 1    | 3      | 1      | 87654321 | 2       | "this is also a tip"
SELECT v.up, v.down, (v.up - v.down) AS rating, t.tip_id, t.tip_date, t.user_id, t.tip_text
FROM tips AS t
INNER JOIN votes AS v
ON t.tip_id = v.tip_id
WHERE challenge_id=1
ORDER BY rating DESC;
然后可以在PHP中设置
WHERE
子句的challenge\u id值,然后再将其传递给mysql。我认为这应该会告诉你你想要什么,尽管因为我使用了
内部连接
,你需要确保“提示”中的每一行都有一行“投票”,否则会被忽略

编辑:

根据新信息(对不起,我之前没有正确阅读问题,希望这次我答对了!):

我刚刚在SQLite3(在简化表上)中测试了这一点,它似乎工作正常。我使用的数据是:

sqlite> select * from votes
   ...> ;
tip_id      vote      
----------  ----------
2           1         
2           1         
2           1         
2           0         
2           0         
3           0         
3           0         
3           0         
3           1         
4           0         
4           0         
4           1         
4           1         
4           1         
4           1    
结果如下:

up          down        rating      tip_id      challenge_id  user_id   
----------  ----------  ----------  ----------  ------------  ----------
4           2           2           4           1             4         
3           2           1           2           1             2         
1           3           -2          3           1             3         

好的,我最终改变了ianhales的查询,得到了我想要的。通过他的更新wuery,我得到了正确的计数,但由于内部连接,我没有得到没有投票权的提示。我的更改很简单,但效果很好:

SELECT
  COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END) AS up,
  COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END) AS down,
  (COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END)) AS rating,
  T.*
  FROM tips T
  LEFT JOIN votes V
  ON T.tip_id = V.tip_id
  WHERE T.challenge_id = 10
  GROUP BY T.tip_id
  ORDER BY rating DESC
这将获取所有提示,即使它们没有投票权,并按降序对它们进行排序,以便更高级别的提示出现在列表的第一位


你太棒了,你可以期待你的名字出现在我的项目的信用卡上。非常感谢。

您肯定不会有两行具有相同的
tip\u id
。因为每个提示的
提示id
将不同?还是我遗漏了一些简单的东西?第一个表中使用的MySQL语句是什么?可以包含(部分)有效的查询吗?我现在正在工作,回家后会发布半有效的查询。至于tip_id,在tips表中,不,每一行都有自己的tip_id。但是,在投票表中,我使用tip_id作为父项将投票与tip相关联,因此投票表中可以有任意数量的具有相同tip_id的行。我继续使用一些新信息编辑了我的帖子。实际上没有名为“up”或“down”的列在投票表中,只有一个布尔值,其中0表示反对票,1表示赞成票。当我提出我的半工作查询时,它会更有意义。我试过了,它确实得到了正确的计数,但有一个问题,它只得到有投票权的提示。对于没有投票的提示,将不返回任何内容。有办法解决这个问题吗?我试着按T.tip_id分组,做一个左外连接,没有骰子。如果我带着提示加入投票表,而不是反过来。。。