这可以在一个查询中完成吗?

时间:2010-11-24 11:13:37

标签: database database-design mysql

Table: category  
-- idcategory (PK)  
-- idmember (FK: member that owns category)  

Table: category_shared UNIQUE (idcategory,idmember)   
-- idcategory (FK:referencing table category)  
-- idmember (FK:member being shared with)  

Table: last_viewed UNIQUE (idcategory,idmember)   
-- idcategory (FK:referencing table category)  
-- idmember (FK)  

我想要一个单一的查询,它可以提取成员共享或拥有的所有类别以及最后一次查看该类别。这就是我试过的:

SELECT * FROM (category 
LEFT JOIN category_shared USING (idmember))
INNER JOIN last_viewed ON 
    category.idcategory=last_viewed.idcategory OR 
    category_shared.idcategory=last_viewed.idcategory
WHERE category.idmember = '$member_id' OR category_shared.idmember = '$member_id'

但它为每个唯一类别返回相同行的SIX。整个数据库结构从一开始就是PITA,所以我愿意接受更好的架构建议。

4 个答案:

答案 0 :(得分:3)

是的,好吧,你的一半问题是由于没有一个已解决的数据模型,这会导致SQL无处不在;如果你修复它,SQL会更容易。另一半无法有效使用SQL。

  1. 你没有在其他表中发布信息,所以我不能给你一个相当准确的DM,我只是从你提供的内容,当然对其他相关表做出了很大的假设,这很可能是不正确的。如果您提供信息,我可以提供准确的DM。

    • 只有一位会员是独立类别还是“拥有”?
      • 模仿:“不。”
    • 什么是“共享”类别?
      • 建模:共享与所有权相同;共享类别只是由多个成员拥有的类别
    • 那么,“拥有”类别和“共享”类别之间有什么区别?
    • 我们不知道这些类别是什么(主题?)。在哪种情况下,成员拥有/共享的类别,而不是主题?
    • 您的类别,如果属于,则不应该被称为类别,而是类似于CategoryOwned。
    • 我看不出CategoryViewed如何显示所有视图;它允许每个成员只有一个(最后一个?)视图。 ViewDate在哪里?
      • 建模:作为视图的日志。如果每个成员只需要一个(最后一个)视图,请从PK中删除ViewDate。

    Interim Data Model

  2. 执行联盟等不是一个好主意,除非你绝对必须这样做。现在数据很小;当数据库很大时,你肯定会感受到正在创建的工作表的影响;填充;销毁。从您的要求到目前为止,不需要工会,区别,工作表等。但DM确实存在问题。

  3. SQL。我无法看到您的SQL(或任何其他答案)如何检索“上次[任何成员]查看该类别”的要求。此外,在Unioning等之前,你应该总是尝试让每个集合的SQL正确(返回正确的数据集):你还没有这样做;这就是你有重复行的原因。使用DISTINCT是一种解决问题的愚蠢方法;你在寻求理解方面是正确的。

  4. 我不会尝试为您的模型提供SQL。这是提供的临时数据模型的SQL。显然,这比联盟便宜得多:

    SELECT  [Member]   = Member.Name,
            [Category  = Category.Name,
            [LastView] = ( SELECT MAX(ViewDate)
                FROM  CategoryView
                WHERE CategoryId = cm.CategoryId
                )
    FROM  CategoryMember cm,
          Member         m,
          Category       c
    WHERE cm.MemberId  = '$MemberId'
    AND   m.MemberId   = cm.MemberId
    AND   c.CategoryId = cm.CategoryId

答案 1 :(得分:0)

如果您唯一的问题是返回了多个相同的行,那么DISTINCT应该完成这项工作。

如果这会给您带来性能问题(如果重复行的数量与您指示的一样,则不应该这样),请向您的DBMS供应商投诉或获得更好的DBMS。

答案 2 :(得分:0)

将类别直接加入last_viewed,因为您只显示这些表中的数据,

使用Where IN category_shared限制数据

答案 3 :(得分:0)

(SELECT date_viewed,category.idcategory FROM category INNER JOIN last_viewed USING (idcategory,idmember) WHERE category.idmember='$member_id')
    UNION
(SELECT date_viewed,category_shared.idcategory FROM category_shared INNER JOIN last_viewed USING (idcategory,idmember) WHERE category_shared.idmember='$member_id')

这是我最终使用的,以防有人遇到这样的情况。感谢输入!