代码之家  ›  专栏  ›  技术社区  ›  ekhaled

MySQL-在一对多关系中选择不匹配的数据

  •  0
  • ekhaled  · 技术社区  · 14 年前

    首先,这个问题与PHP和MySQL有关

    这个 People 表格:

    person_id   |   field_1  |  field_2  |  other_fields... 
    

    以及 Notes

    note_id   |  person_id  |  created_timestamp  |  other_fields... 
    

    这个 表与 笔记 表格。。。
    笔记 person_id

    现在。。。
    我要找到所有的 people 谁还没有 note
    我现在的做法是:

    1. 带有不同 人员id 和一个 created_timestamp 'time(31*86400)' (不准确。。我知道,但符合我的需要)
    2. 到临时数组 $temp
    3. 桌子
    4. in_array() 人员id 具有 $临时

    笔记 .

    有人有更好的解决办法吗。理想情况下,只需一个SQL查询就可以实现。

    谢谢你找我

    5 回复  |  直到 14 年前
        1
  •  2
  •   halfdan    14 年前
    SELECT person_id FROM People WHERE person_id NOT IN 
        (SELECT person_id FROM Note 
            WHERE created_timestamp > DATE_SUB(CURDATE(), INTERVAL 30 DAY))
    

    这假设create\u timestamp的类型为“DATE”、“timestamp”或“DATETIME”。如果您在这里使用unix时间戳,请使用 FROM_UNIXTIME(created_timestamp)

        2
  •  1
  •   Elemental    14 年前

    Select * from people where PersonID NOT in 
      (select PersonID from Notes where Created_Timestamp>...)
    

    另一个选择是对Notes进行右外连接,并只对Notes进行过滤Notes.PersonID为NULL,它只提供与Notes不匹配的行。

        3
  •  1
  •   MikeTheReader    14 年前

    我认为这应该奏效:

        4
  •  1
  •   Victor Nicollet    14 年前

    如果这很关键,您可以考虑进行非规范化:将最后一个注释的时间戳存储在user表中,并对该列进行索引。

    否则,无法避免遍历整个人表,因此请在note表的(person\u id,timestamp)对上添加索引,并使用左联接或子查询:

    SELECT * FROM people 
             LEFT JOIN notes ON people.person_id = notes.person_id
                            AND notes.created_timestamp < NOW() - INTERVAL 30 DAY
    WHERE notes.person_id IS NULL
    
    SELECT * FROM people
    WHERE person_id NOT IN (SELECT person_id FROM notes
                            WHERE created_timestamp < NOW() - INTERVAL 30 DAY)
    
        5
  •  1
  •   OMG Ponies    14 年前

    左联接/为空

       SELECT p.*
         FROM PEOPLE p
    LEFT JOIN NOTES n ON n.person_id = p.person_id
                     AND n.created_timestamp >= DATE_SUB(NOW(), INTERVAL 30 DAY)
        WHERE n.note_id IS NULL
    

    不存在

    SELECT p.*
      FROM PEOPLE p
     WHERE NOT EXISTS(SELECT NULL
                        FROM NOTES n
                       WHERE n.person_id = p.person_id
                         AND n.created_timestamp >= DATE_SUB(NOW(), INTERVAL 30 DAY))
    

    不在

    SELECT p.*
      FROM PEOPLE p
     WHERE p.person_id NOT (SELECT n.person_id
                              FROM NOTES n
                             WHERE n.created_timestamp >= DATE_SUB(NOW(), INTERVAL 30 DAY))
    

    这个 LEFT JOIN IS NULL is the most efficient on MySQL when the columns compared are not nullable . 如果 the columns compared were nullable, NOT IN and NOT EXISTS are more efficient