我正在使用SQLite,稍后将移植到MySQL(5)。
我想知道我是否正在做一些我不应该做的事情。我故意设计,所以我会比较0而不是1(我改变了hasApproved到NotApproved做这个,没什么大不了的,我没有写任何代码)。我被告知我永远不需要写一个子查询,但我在这里。我的投票表只是id, ip, postid
(我不认为我可以将该子查询写成连接而不是?)而且这几乎是我的想法。
命名约定我并不关心,因为表是通过反射创建的,而且遍布整个地方。
select
id,
name,
body,
upvotes,
downvotes,
(select 1 from UpVotes where IPAddr=? AND post=Post.id) as myup,
(select 1 from DownVotes where IPAddr=@0 AND post=Post.id) as mydown
from Post
where
flag = '0'
limit ?, ?"
答案 0 :(得分:1)
我猜你正在努力确保用户只在每个帖子上投票一次。
我不会 - 我不 - 使用单独的表格进行投票和投票。将投票类型添加到您的投票表中,您将不需要相关的子查询。
答案 1 :(得分:1)
以下是我的意见:
似乎表“UpVotes”和“DownVotes”具有相同的结构,可以合并到一个表中。
表“Post”和“Up / DownVotes”之间的关系可以用外键约束。
答案 2 :(得分:1)
由于您正在询问良好做法......您的帖子表格中出现的“upvotes”和“downvotes”看起来像是在复制数据库中的数据。这是一个问题,因为现在你总是要担心数据是否同步和正确。如果你想知道upvotes的数量然后计算它们,也不要将它们存储在Post表中。我不是肯定你正在做的事情,但这是猜测。
在您的查询上...使用JOINed子查询而不是如何使用它可能会获得更好的性能。使用标量子查询作为列,它们必须为返回的每一行运行一次。如果你返回一堆行,这可能是一个非常大的性能影响。相反,尝试:
SELECT
P.id,
P.name,
P.body,
P.upvotes,
P.downvotes,
COALESCE(UV.cnt, 0) AS upvotes2,
COALESCE(DV.cnt, 0) AS downvotes2
FROM
dbo.Posts P
LEFT OUTER JOIN (SELECT post_id, COUNT(*) cnt FROM dbo.UpVotes GROUP BY post_id) AS UV ON UV.post_id = P.id
LEFT OUTER JOIN (SELECT post_id, COUNT(*) cnt FROM dbo.DownVotes GROUP BY post_id) AS DV ON DV.post_id = P.id
将它与您自己的查询进行比较,看看它是否能为您提供更好的效果。
编辑:其他几张海报都主张单张桌子进行上/下投票。他们绝对正确。这使查询更容易,也可能更快:
SELECT
P.id,
P.name,
P.body,
P.upvotes,
P.downvotes,
SUM(CASE WHEN V.vote_type = 'UP' THEN 1 ELSE 0 END) AS upvotes2,
SUM(CASE WHEN V.vote_type = 'DOWN' THEN 1 ELSE 0 END) AS downvotes2,
FROM
dbo.Posts P
LEFT OUTER JOIN Votes V ON
V.post_id = P.id
GROUP BY
P.id,
P.name,
P.body,
P.upvotes,
P.downvotes
答案 3 :(得分:0)
您可以使用连接来实现相同的功能,我希望连接比嵌入选择更有效。