Php 如何选择所有未发布的用户,按日期分组?

Php 如何选择所有未发布的用户,按日期分组?,php,mysql,laravel,period,Php,Mysql,Laravel,Period,我有用户表和帖子表。我可以轻松选择从2020年1月1日到2020年4月1日发布的所有用户,并按日期对结果进行分组: User::whereDoesntHave('posts', function($query) use($first_date, $last_date) { $query->whereBetween('posts.date', [$first_date, $last_date]); }) ->get(); 我需要帮助的是,让那些从2020年1月1日到2020年

我有用户表和帖子表。我可以轻松选择从2020年1月1日到2020年4月1日发布的所有用户,并按日期对结果进行分组:

User::whereDoesntHave('posts', function($query) use($first_date, $last_date) {
    $query->whereBetween('posts.date', [$first_date, $last_date]);
})
->get();
我需要帮助的是,让那些从2020年1月1日到2020年4月1日没有发帖的用户按日期分组。这意味着我希望所有在特定日期范围内的POST表上没有行的用户。可能吗

我希望得到结果的示例:

01/01/2020
- John
- Ana
- Sandra

01/02/2020
- Ana
- Sandra

01/03/2020
- John
- Lucas
- Charlie

01/04/2020
- Charlie
- Ana



users table:

id = (int)
name (varchar)

posts table

id (int)
user_id (int)
msg (text)
date (datetime)

我们可以使用反连接模式

简单地说。。。一个查询,返回所有日期和用户,外部联接包括帖子中的匹配行,然后从帖子中排除所有具有匹配行的行,留下帖子中没有匹配行的行

作为起点,我们可以得到所有用户的所有日期的笛卡尔乘积交叉联接

SELECT d.dt
     , u.user_name
  FROM ( SELECT '2018-01-01' + INTERVAL 0 DAY AS dt
         UNION ALL SELECT '2018-01-01' + INTERVAL 1 DAY
         UNION ALL SELECT '2018-01-01' + INTERVAL 2 DAY
         UNION ALL SELECT '2018-01-01' + INTERVAL 3 DAY
       ) d
 CROSS
  JOIN `USERS` u
 ORDER
    BY d.dt
     , u.user_name
要从查询返回行,我们需要这些行的源。我们无法仅从POSTS表返回缺少的行。我们需要完整的行集,然后可以与POSTS表的内容进行比较

我们可以添加外部联接,以标识匹配的行,然后排除具有匹配的行

SELECT d.dt
     , u.user_name
  FROM ( SELECT '2018-01-01' + INTERVAL 0 DAY AS dt
         UNION ALL SELECT '2018-01-01' + INTERVAL 1 DAY
         UNION ALL SELECT '2018-01-01' + INTERVAL 2 DAY
         UNION ALL SELECT '2018-01-01' + INTERVAL 3 DAY
       ) d
 CROSS
  JOIN `USERS` u

    -- anti-join, exclude rows that have a matching row in posts
  LEFT
  JOIN `POSTS` p
    ON p.user_name = u.user_name
   AND p.dt        = d.dt
 WHERE p.dt IS NULL

 ORDER
    BY d.dt
     , u.user_name
示例查询返回每个日期,以及在该日期没有帖子的用户。这满足了一个可能的解释相当模糊的规范谁没有张贴从。。。到并按日期分组

为了使此查询返回预期结果,我们可以手工制作示例数据:

USERS   
user_name
--------- 
Ana
Charlie
John
Lucas
Sandra

我们可以使用带有相关子查询的NOT EXISTS来代替反联接,以返回等效的结果

SELECT d.dt
     , u.user_name
  FROM ( SELECT '2018-01-01' + INTERVAL 0 DAY AS dt
         UNION ALL SELECT '2018-01-01' + INTERVAL 1 DAY
         UNION ALL SELECT '2018-01-01' + INTERVAL 2 DAY
         UNION ALL SELECT '2018-01-01' + INTERVAL 3 DAY
       ) d
 CROSS
  JOIN `USERS` u

 WHERE NOT EXISTS
       ( SELECT 1
           FROM `POSTS` p
          WHERE p.user_name = u.user_name
            AND p.dt        = d.dt
       )

 ORDER
    BY d.dt
     , u.user_name

您可以使用此返回的子查询执行反向选择。从userid不在的表中选择*从上一个结果中选择userid,其中。。。;该小组是否会按日期公布所有结果?我没有mysql的技能,所以我真的不知道如何进行查询,我希望有人能为我键入查询,这样我就可以将其调整到laravel frameworkWell。不会有从2020年1月1日发布到2020年4月1日的日期,因为这是一个范围。如果你希望每个日期都是不同的,请描述一下你的表格。你自己有没有尝试过解决这个问题?欢迎来到SO。请看:你确定这会奏效吗?我正在尝试使用我的表和字段调整您的查询。当你使用:和p.dt=d.dt??顺便说一句,只有POST有一个数据字段。如果它是一个日期时间字段,这会起作用吗?没有规范,没有表的定义,我们只是猜测。注意,我提供的示例表有一个日期数据类型的dt列。如果POSTS表有一个DATETIME、TIMESTAMP或VARCHAR数据类型列,您可以从中判断post的日期,那么当然可以修改查询。使用查询中使用的任何条件来获取用户名在特定日期(例如2020-01-03)的帖子,并对其进行调整。确定DATETIME dt是否落在特定日期的标准模式是范围比较,例如,p.dt>='2018-01-03'和p.dt<'2018-01-04'。如果POSTS table dt列是DATETIME,然后我会做,p.dt>=d.dt+间隔0天,p.dtSELECT d.dt , u.user_name FROM ( SELECT '2018-01-01' + INTERVAL 0 DAY AS dt UNION ALL SELECT '2018-01-01' + INTERVAL 1 DAY UNION ALL SELECT '2018-01-01' + INTERVAL 2 DAY UNION ALL SELECT '2018-01-01' + INTERVAL 3 DAY ) d CROSS JOIN `USERS` u WHERE NOT EXISTS ( SELECT 1 FROM `POSTS` p WHERE p.user_name = u.user_name AND p.dt = d.dt ) ORDER BY d.dt , u.user_name