【问题标题】:Getting data for every single day in SQL在 SQL 中获取每一天的数据
【发布时间】:2012-10-22 00:22:04
【问题描述】:

我目前有以下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

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

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 肯定是杀死结果的那个。

【问题讨论】:

    标签: mysql sql date


    【解决方案1】:

    使用LEFT JOIN 而不是INNER JOIN

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

    INNER JOIN 仅检索在另一张表上至少有一个匹配的行,而LEFT JOIN 检索在 左侧 表上定义的所有行,无论它在另一张表上是否有匹配项( s)。

    更新 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)
    

    **Thorpe Obazee更新

    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。我们也不应该在 c.day 的 GROUP BYORDER BY 中使用 DAYOFMONTH,因为它已经是我们需要的了。

    【讨论】:

    • 我应该提到我已经尝试过了但没有奏效。它似乎应该有效,但它没有。
    • @ThorpeObazee 也许是 site_id = 16 的情况正在扼杀问题,我会更新答案。
    • @ThorpeObazee 哎呀对不起,它应该在查询的外部,等待我会更新答案。
    • @ThorpeObazee 再次尝试更新的查询,记录应按c.day 而非d.created 分组
    • 我在玩您的查询时得到了它。如果您不介意,我会更新您的答案。
    【解决方案2】:

    正如最后一张海报所说,使用 LEFT 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,这将捕获您拥有访问者数据的任何记录为,即使日期不在日历表中。

    希望对您有所帮助。

    凯文

    【讨论】:

    • 如果您阅读了第一个答案中的 cmets,我已经提到过尝试一下。感谢你的信息。我正在我的查询中寻找可能会杀死它的东西。
    • 是的,很抱歉,我是在发布时写的!
    【解决方案3】:

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

    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]
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多