0

我目前有以下 SQL 语句

MySQL 查询:

SELECT
    c.day,
    COUNT(*)
FROM
    calendar c
JOIN
    visitors d
ON  DAYOFMONTH(d.created) = c.day
WHERE
    c.day BETWEEN DAYOFMONTH('2012-10-01') AND DAYOFMONTH('2012-10-31')
AND
    site_id = 16
GROUP BY
    DAYOFMONTH(d.created)
ORDER BY
    DAYOFMONTH(d.created)

我的表:

Calendar

id  | day
---------
1   | 1
2   | 2
3   | 3
...
31  | 31

Visitors

id  | site_id | created
-----------------------------------
1   | 16      | 2012-10-18 11:14:39
2   | 16      | 2012-10-18 11:15:17
3   | 11      | 2012-10-18 11:49:14
4   | 11      | 2012-10-18 11:49:43
5   | 16      | 2012-10-19 11:54:37
6   | 1       | 2012-10-19 05:56:31
7   | 2       | 2012-10-19 05:57:56

我已经按照这个答案的规定创建了表格和日历,但我似乎仍然得到了相同的信息。我只得到我有数据的日期。

day    |   COUNT(*)
---------------------
18     |   2
19     |   1

我还需要检索0没有数据的日期。

更新:

I tried this:
SELECT *
FROM calendar c
LEFT JOIN visitors d
ON  DAYOFMONTH(d.created) = c.day

SELECT *
FROM calendar c
LEFT JOIN visitors d
ON  DAYOFMONTH(d.created) = c.day
WHERE  site_id = 16

我可以确认那site_id = 16肯定是杀死结果的那个。

4

3 回答 3

1

使用LEFT JOIN而不是INNER JOIN

SELECT ...
FROM   calendar c 
       LEFT JOIN  visitors d
         ON DAYOFMONTH(d.created) = c.day
WHERE...

INNER JOIN仅检索在另一个表上具有至少一个匹配项的行,同时检索在左侧LEFT JOIN表上定义的所有行,无论它在其他表上是否有匹配项。

更新 1

SELECT  c.day,
        COUNT(*)
FROM    calendar c
        LEFT JOIN
        (
            SELECT *
            FROM   visitors
            WHERE  site_id = 16
        ) d ON  DAYOFMONTH(d.created) = c.day
WHERE c.day BETWEEN DAYOFMONTH('2012-10-01') AND DAYOFMONTH('2012-10-31')
GROUP BY DAYOFMONTH(c.day)
ORDER BY DAYOFMONTH(c.day)

**索普奥巴泽更新

SELECT  c.day,
        COUNT(site_id)
FROM    calendar c
        LEFT JOIN
        (
            SELECT *
            FROM   visitors
            WHERE  site_id = 16
        ) d ON  DAYOFMONTH(d.created) = c.day
WHERE c.day BETWEEN DAYOFMONTH('2012-10-01') AND DAYOFMONTH('2012-10-31')
GROUP BY c.day
ORDER BY c.day

我们不能使用COUNT(*),因为它会1每天返回。我们也不应该在 and 中使用DAYOFMONTHon c.day,GROUP BY因为ORDER BY它已经是我们需要的了。

于 2012-10-22T00:23:30.103 回答
0

正如最后一张海报所说,使用 LEFT JOIN 但用于澄清。

想象一下您的日历表是​​左表,访问者表是右表

使用 INNER JOIN

FROM Calendar c
INNER JOIN Visitors v
ON c.Date = v.Date

左侧和右侧都必须匹配。

使用左连接

FROM Calendar c
LEFT JOIN Visitors v
ON c.Date = v.Date

您将返回 LEFT 表(日历)中的所有记录,并且仅返回与 RIGHT 表(访问者)匹配的记录,对于没有任何匹配访问者数据的所有日历日期,您将保留 NULL(当然,除非您处理这个像COALESCE这样的东西)

右连接

FROM Calendar c
RIGHT JOIN Visitors v
ON c.Date = v.Date

您将返回右表(访问者)中的所有记录,并且仅返回与左表(日历)匹配的记录,对于未找到匹配项的列值,您将获得 NULLS,这将捕获您拥有访问者数据的任何记录,甚至如果日期不在日历表中。

希望有帮助。

凯文

于 2012-10-22T00:36:17.883 回答
0

回答这个问题的另一个建议是移动

WHERE site_id = 16

进入 JOIN,例如,

SELECT
 c.[Day]
,COUNT(v.[id])
FROM TestDB.dbo.Calendar c
LEFT JOIN TestDB.dbo.Visitor v
ON c.[Day] = DATEPART(d,v.Created)
AND v.[SiteID] = 16
GROUP BY c.[Day]
ORDER BY c.[Day]

我个人不喜欢使用派生表,因为我已经看到使用更本机连接的性能要好得多,但是,我通常处理具有数百万行的数据集。

于 2012-10-22T01:27:10.733 回答