我正在尝试整理一个广告的效果报告,显示一天中的观看次数和点击次数。视图和点击存储在具有不同结构的单独表中,因此我认为我必须执行联合。
我已阅读并理解this fantastic piece。它帮助了我,但我认为这比那里解释的例子更复杂。希望得到社区的一些帮助。
这是我的views
表,它存储广告在一天内的观看量的计数器。
+-------------+--------------+
| COLUMN_NAME | COLUMN_TYPE |
+-------------+--------------+
| ad_day_id | bigint(13) |
| advert_id | bigint(20) |
| date | date |
| views | mediumint(6) |
+-------------+--------------+
这是我的clicks
表,它单独存储每次点击。
(因为它们与问题无关而遗漏了一些列)
+-------------+---------------------+
| COLUMN_NAME | COLUMN_TYPE |
+-------------+---------------------+
| id | bigint(20) unsigned |
| advert_id | bigint(20) |
| timestamp | timestamp |
+-------------+---------------------+
结果应该是这样的(没有使用实数,只是为了显示格式):
+------------+-------+--------+
| event_date | views | clicks |
+------------+-------+--------+
| 2016-05-09 | 25 | 4 |
| 2016-05-10 | 2 | |
| 2016-05-11 | 105 | 10 |
| 2016-05-13 | 96 | 7 |
| 2016-05-14 | | 1 |
+------------+-------+--------+
关于结果:
关闭代码......这就是我目前所拥有的:
SELECT
$views_table.date AS event_date,
$views_table.views,
'' AS clicks
FROM
$views_table
WHERE
( $views_table.date BETWEEN '$from_date' AND '$to_date' )
AND $views_table.advert_id=$advert_id
UNION
SELECT
CAST($clicks_table.timestamp AS DATE) AS event_date,
'' AS views,
COUNT($clicks_table.advert_id) AS clicks
FROM
$clicks_table
WHERE
( CAST($clicks_table.timestamp AS DATE) BETWEEN '$from_date' AND '$to_date' )
AND $clicks_table.advert_id=$advert_id
GROUP BY
event_date
ORDER BY
event_date ASC;
关于代码的一些注释:
在撰写这个问题时,我更好地格式化了代码,为了便于阅读,我改变了解决我初始问题的select语句的顺序。显然,两个选择必须具有相同的列并且具有相同的顺序。
我想我差不多了,因为这是我目前的结果:
+------------+-------+--------+
| event_date | views | clicks |
+------------+-------+--------+
| 2016-05-09 | 1 | |
| 2016-05-09 | | 1 |
| 2016-05-10 | 2 | |
| 2016-05-11 | 105 | |
| 2016-05-11 | | 7 |
| 2016-05-13 | 96 | |
| 2016-05-13 | | 16 |
| 2016-05-14 | 2 | |
| 2016-05-14 | | 1 |
| 2016-05-15 | 2 | |
| 2016-05-15 | | 2 |
+------------+-------+--------+
我剩下的问题是重复日期。我该如何解决这个问题? 非常感谢那些善意回答的人!
答案 0 :(得分:1)
这不是一个简单的联盟,而是一个联盟和联盟。因此,您需要一个联合来从视图和点击表中获取日期的组合列表。然后,您需要在日期列表中左键加入视图并单击表格:
select ds.event_date, max(v.views) views, count(c.clicks) clicks
from
(select distinct date as event_date from views
union distinct
select distinct date(timestamp) from clicks) ds
left join views v on ds.event_date=v.date
left join clicks c on ds.event_date=date(c.timestamp)
where ...
group by ds.event_date
答案 1 :(得分:1)
我稍微修改了你的查询(参见内联注释)并将其包装在子查询中以在外部查询中使用GROUP BY event_date
。
SELECT event_date, MAX(views) AS views, MAX(clicks) AS clicks
FROM (
SELECT
views.date AS event_date,
views.views,
0 AS clicks -- '' causes strange results on sqlfiddle
FROM
views
WHERE
( views.date BETWEEN '2016-05-09' AND '2016-05-15' )
AND views.advert_id=1
UNION
SELECT
CAST(clicks.timestamp AS DATE) AS event_date,
0 AS views, -- '' causes strange results on sqlfiddle
COUNT(clicks.advert_id) AS clicks
FROM
clicks
WHERE
( CAST(clicks.timestamp AS DATE) BETWEEN '2016-05-09' AND '2016-05-15' )
AND clicks.advert_id=1
GROUP BY
event_date
-- ORDER BY is useless here
) sub
GROUP BY event_date
ORDER BY event_date
您也可以使用CAST(clicks.timestamp AS DATE)
代替DATE(clicks.timestamp)
,并希望MySQL将来会使用索引。