我正在尝试完成以下操作 - 我希望在每个客户的网站上看到按日历周分组的会话。以下是我到目前为止要完成的查询:
SELECT o.name
, s.organization_id
, count(s.id) as num_of_sessions
, CONCAT(s.created_at, ' - ', s.created_at + INTERVAL 6 DAY) AS week
FROM triton.sessions s
, triton.organizations o
where o.id=s.organization_id
and s.organization_id in (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72)
GROUP BY s.organization_id, WEEK(s.created_at)
ORDER BY o.name, WEEK(s.created_at);
问题在于,客户没有网站会话的周数不报告为0 - 而是报告该周没有报告。这是一个问题,因为我无法轻松地将数据转换为Excel,并为每个客户的会话创建图表。
为了尝试解决此问题,我创建了一个临时周表,其中每周的值为1-52,并尝试使用此链接中建议的方法:Summarise by week, even for empty rows
面临的挑战是,当我进行左外连接时,我会为组织丢失组。
这是一个工作的SQL,用于按周分组(在尝试按组织分组之前):
select w.weeknum
, sess.club
, sess.organization_id
, count(sess.club) from weeks w
left outer
join ( select o.name as club
, s.organization_id
, s.created_at
from sessions s
, organizations o
where s.organization_id in (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72)
and o.id=s.organization_id
) sess
on (w.weeknum = extract(week from sess.created_at))
group by w.weeknum
上面的代码只返回52行(每周1行),计数给我每周会话数。
我现在想扩展上面的代码来完成上述操作,但每个组织。我应该回到52 * N行,其中N是组织的数量。我认为这就像将组织添加到groupby语句一样简单,但它只返回了有sesssions的周(导致我从一开始就遇到的问题)。这是查询:
select w.weeknum
, sess.club
, sess.organization_id
, count(sess.club)
from weeks w
left outer
join ( select o.name as club
, s.organization_id
, s.created_at
from sessions s
, organizations o
where s.organization_id in (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72)
and o.id=s.organization_id
) sess
on (w.weeknum = extract(week from sess.created_at))
group by sess.club, w.weeknum
order by sess.club
有没有人有任何其他建议可以实现我的目标?基本上对于我的每个客户,我希望按周查看会话列表(即使他们在特定的一周内没有会话)。
答案 0 :(得分:0)
使用cross join
获取行,然后使用left join
:
select w.weeknum, s.club, s.organization_id, count(s.club)
from weeks w cross join
organizations o left outer join
sessions s
on w.weeknum = extract(week from s.created_at) and
o.id = s.organization_id
where o.id in (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72)
group by w.weeknum, s.club, s.organization_id;
答案 1 :(得分:0)
只需获取原始查询,并将其包装在内部并将其用作内联视图。
看起来你想知道你想要一个返回你想要返回的所有行的行源,然后是一个左连接到你的内联视图。
你有这个部分:
from weeks w
只需对要返回的所有organization_id进行交叉连接。
看起来organization_id可能是组织表的主键。如果是这种情况,那么此查询将返回您想要的集合:
SELECT v.name
, v.organization_id
FROM triton.organizations v
WHERE v.organization_id (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72)
ORDER BY v.organization_id
所以只需将该集与weeks
rowsource:
SELECT v.name
, v.organization_id
, w.weeknum
FROM triton.organizations v
CROSS
JOIN weeks w
WHERE v.organization_id (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72)
ORDER
BY v.organization_id
, w.weeknum
如果您只想要weeks
表中的子集,只需在WHERE
子句中添加谓词,例如
AND w.weeknum BETWEEN 0 AND 104
对于每个organization_id,这应该每周返回一次。
一旦你开始工作,现在只需在你的原始查询中添加一个“外连接”,在SELECT列表中添加一个表达式,它可以获得一个与weeknum匹配的值。
我对涉及created_at
的表达感到困惑。由于created_at
,GROUP BY
返回的值不确定。如果您想要“最早”和/或“最新”值,请使用MIN和MAX聚合。 (假设created_at
是DATE,DATETIME或TIMESTAMP。)
SELECT v.name
, v.organization_id
, w.weeknum
, IFNULL(t.num_of_sessions,0)
FROM triton.organizations v
CROSS
JOIN weeks w
LEFT
JOIN (
-- query to get session counts goes here
) t
ON t.organization_id = v.organization_id
AND t.weeknum = w.weeknum
WHERE v.organization_id (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72)
ORDER
BY v.organization_id
, w.weeknum
在外部查询中,引用视图返回的num_of_sessions
列。 IFNULL功能是用零替换“缺失”计数的便捷方式。
获取“计数”的查询可能类似于:
SELECT s.organization_id AS organization_id
, WEEK(s.created_at) AS weeknum
, COUNT(s.id) AS num_of_sessions
, MIN(s.created_at) AS min_created_at
, MAX(s.created_at) AS max_created_at
FROM triton.sessions s
WHERE s.organization_id IN (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72)
GROUP
BY s.organization_id
, WEEK(s.created_at)
如果原始查询的这一部分的意图:
CONCAT(s.created_at, ' - ', s.created_at + INTERVAL 6 DAY) AS week
是显示一周的开始日期和结束日期,然后从周表中的值生成。 (如果有一个组织,在一个星期内只有一个交易,并且它在星期四,那个表达将产生“星期四到星期三”。这样做没有错,但我强烈怀疑这不是什么你真的想要。
如果你想要每周的“星期六星期六”,那么最好从周末表中返回。
如果您想要组织会话的实际日期,请使用created_at的MIN()和MAX()值,并将它们连接起来。这些不一定是“星期六到星期六”,但任何返回的日期都将在“一周之内”。