Php 如何选择所有未发布的用户,按日期分组?
我有用户表和帖子表。我可以轻松选择从2020年1月1日到2020年4月1日发布的所有用户,并按日期对结果进行分组: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年
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.dt
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