好的,我在这里遇到了一个有趣的问题。我有两个表,提示和投票。提示看起来像这样:
tip_id, challenge_id, user_id, ip_address, tip_date, tip_text
投票看起来像这样:
tip_id, ip_address, vote_date, vote
用户可以发布挑战提示,然后其他用户可以用拇指向上或向下对提示进行投票。投票中的投票字段是bool,0表示拇指向下,1表示拇指向上。挑战可以有任意数量的提示。
我一直绞尽脑汁,我无法让它发挥作用。我需要一个查询,可以获得特定提示的上下投票数,这两个数字的差异(因此如果有2个投票和1个投票,差异将是1)作为评级,还有从提示表中提示数据,然后先按最高评级对其进行排序。假设我们有两个提示,a和b:
a:3 up,2 down(diff:1) b:4上,1下(差异:3)
在这种情况下,b会首先出现,因为它的评级高于a,上下票数差异较大。
所以,例如,假设我有一个id为1的小费,其中有4个投票和2个投票,这意味着相差2,这个小贴士与挑战ID 5相关联,我的回报可能看起来像这样:
up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3 | 2 | 1 | 1 | 12345678 | 1 | "this is a tip"
现在我已经能够做到这一点,但是如果有多个挑战提示,我遇到问题就是获得多行。假设挑战ID 5有两个提示,那么我应该得到这样的结果:
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"
每个提示在结果中都有自己的行。现在正在发生的事情是我得到一行,其中上下值是该挑战的上下投票总数,而不是小费。因此,使用上面的第二个示例,而不是两个单独的行,我将得到一行,其值为7,向下为3,即该挑战的所有提示的向上和向下投票的总数。
我确信这将涉及加入和排序,以及分组,但我不关心查询有多复杂,我只是不想在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
这可以获得我需要的一切,特定挑战的所有提示和投票,每个提示都有一个新行(而不是像以前那样的聚合计数)。问题是,我的上下投票,以及评级,是它应该是的两倍。因此,如果我有一个有3个投票和1个投票的小费,所以等级为2,这个查询将显示我有6个投票和2个投票评级为4.我想我可以简单地划分使用PHP编号为2,但这不能解决问题,它只是一个绑定。任何人都可以看到我为什么得到两倍的数量?我会继续搞乱它,也许尝试LEFT JOIN,希望我能弄明白,但是再多几双眼睛会很好。
答案 0 :(得分:2)
这样的事情怎么样:
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传递给mysql之前在PHP中设置WHERE
子句的challenge_id值。我认为这应该会给你你想要的东西,虽然因为我使用了INNER JOIN
你需要确保“提示”中的每一行都有一行“投票”或者它会被忽略。
编辑:
基于新信息(对不起,我之前没有正确阅读过这个问题,希望这次我能说得对!):
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
INNER JOIN tips AS T
ON T.tip_id = V.tip_id
WHERE T.challenge_id = 1
GROUP BY V.tip_id
ORDER BY rating DESC;
我刚刚在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
答案 1 :(得分:-1)
好的,我最终改变了ianhales provided并获得我想要的查询。随着他更新的wuery,我得到了正确的数量,但由于INNER JOIN,我没有获得没有投票的提示。我的改变很简单,但它们完美地运作:
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
这会获得所有提示,即使他们没有投票,也会按降序排列 rating ,以便在列表中首先显示评分较高的提示。
你太棒了,你可以期待你的名字出现在我项目的学分中。非常感谢你。