我想列出用户在我的网站上最近的活动,而不会做太多的查询。我有一个表格,列出了用户对日期所做的所有事情。
page_id - reference_id - reference_table - created_at - updated_at
reference_id
是我需要在reference_table中搜索的ID(例如:comments)。如果我在活动表上执行SELECT
,则必须查询:
SELECT * FROM reference_table where id = reference_id LIMIT 1
活动可以是评论,页面更新或订阅。根据它的不同,我需要从数据库中的其他表中获取不同的数据
例如,如果是评论,我需要获取作者的姓名,评论,如果是我需要获取orignal评论用户名的回复等等。
我查看了UNION关键字以结合我的所有表,但是我收到了错误
1222 - 使用的SELECT语句具有不同的列数
并且使其工作似乎相当复杂,因为列的数量必须匹配,并且我的表中没有任何表具有相同数量的表,并且我不喜欢创建列以获得它的乐趣。
我还查看了CASE语句,如果我没记错的话,还需要匹配的列数(虽然我可能错了)。
有没有人知道如何在不做太多查询的情况下列出用户的近期活动?
我正在使用PHP和MySQL。
答案 0 :(得分:4)
您可能希望将不同的活动拆分为不同的表格。这将使您更灵活地查询数据。
如果您选择使用UNION,请确保在每个由UNION组成的选择查询中使用相同数量的列。
修改强> 我对我的回答表示赞同,所以也许我可以给出更好的解释。
将表拆分为单独的表和UNION
我推荐了这种技术,因为它可以让您更清楚地了解您要查询的资源。使用单个表进行插入很方便,但是您始终必须执行单独的查询才能与其他表连接以获取有意义的信息。此外,根据存储在该行中的数据,您的数据库模式将被单个列进行模糊处理,该列是不同表的外键。
您可以拥有评论,更新和订阅的表格。这些将拥有自己的数据,可以单独查询。例如,如果您想查看所有用户活动,可以按照以下方式轻松使用UNION:
(SELECT 'comment', title, comment_id AS id, created FROM comment)
UNION
(SELECT 'update', title, update_id as id, created FROM update)
UNION
(SELECT 'subscription', title, subscription_id as id, created
FROM subscription)
ORDER BY created desc
这将为您提供列表视图。然后,您可以链接到每种类型的详细信息或在ajax调用中加载它。
您可以使用当前使用的方法完成此操作,但这实际上将消除对'reference_table'的需要,并将以更清洁的方式完成相同的操作(IMO)。
答案 1 :(得分:1)
问题是UNION应该只用于将类似的记录集放在一起。如果您尝试统一两个不同的查询(例如,提取了不同的列),那就是错误。
如果查询的性质不同(具有不同的列数或数据类型),则需要进行多个不同的查询并将它们全部分开处理。
另一种方法(不太优雅,我猜)是LEFT JOIN你的活动表与所有其他的,所以你最终会有一个包含很多列的记录集,你需要检查每一行哪个应根据活动性质使用列。
同样,我宁愿坚持使用第一个,因为第二个是一个相当稀疏的recorset。
答案 2 :(得分:1)
使用UNION,只要所有列具有相同的数据类型,就不必从每个表中获取所有列。
所以你可以这样做:
SELECT name, comment as description
FROM Comments
UNION
SELECT name, reply as description
FROM Replies
如果Comments
和Replies
列数相同,则无关紧要。
答案 3 :(得分:0)
这实际上取决于您网站上的流量。从逻辑上讲,联合方法是直截了当的,也可能是正确的,但如果您的站点负载很重,那么您的性能会受到影响,因为UNIONed查询的索引很难。
加入可能会很好,但同样,在性能和代码清晰度方面,这不是最好的方法。
另一种完全不同的方法是创建一个“活动”表,该表将使用活动进行更新(除了真实活动之外,仅用于此目的)。在旧的数据库正确性方面,您应该避免使用这种方法,因为它会在您的系统上创建重复数据,但是,我发现它在性能方面非常有用。
[关于UNION方法的另一个注意事项,如果您决定采用它:如果参数长度不同,您可以在某些联合上选择SELECT伪造参数,例如..(SELECT UserId,UserName FROM users)UNION (SELECT 0,来自笔记的UserName)