包括使用限制的所有日期?

时间:2014-07-08 11:27:54

标签: mysql database datetime time-series

我想要从8月1日到8月31日获取所有行但限制为1500行,但是,它必须包括从1到31的所有可能天数。所以从每天我预计大约48行。

SQL Query如何实现?

我已尝试过这个SQL查询,但它不会包含所有日期,因为我使用的是limit

SELECT * FROM table1 
      WHERE `submit` >= '2014-08-01' AND  `submit` <=  '2014-08-31' 
order by `submit`
      LIMIT 1500

更新

它应该从1到31获得所有可能的天数,如果任何天没有足够的行 - 那么包括任何天的剩余行。例如,如果8月7日没有记录,那么任何其他日子都应该包含更多行。

UPDATE2:

假设submit >= '2014-08-01' AND submit <= '2014-08-31'有3000行,但我只想要从01到31的1000行(如果可能的话)。

每天应该有大约32行。

例如

8月01日有32行

8月02日有32行

08年8月只有0行

08年8月只有0行

05年8月有32行

8月31日有32行

3 个答案:

答案 0 :(得分:0)

这是一个麻烦的要求,因为它要求在不可预测的情况下无法预测数据的遗漏。这是给审计员带来坏梦的事情(更不用说程序员了)。它可以帮助您弄清楚您要对此结果集做些什么,并收紧您的要求。

假设您的表具有自动递增的唯一id列,这里的查询将从表中检索每个日期的最后一行。

        SELECT 0 AS priority, t.* FROM table1 AS t
         WHERE id IN (SELECT MAX(id) AS id FROM table1 GROUP BY DATE(submit))

然后,您可以执行此操作以获取剩余的行:

        SELECT 1 AS priority, t.* FROM table1 AS t
         WHERE id NOT IN (SELECT MAX(id) AS id FROM table1 GROUP BY DATE(submit))

您可以将这些联合起来,对它们进行排序并限制它们。

  SELECT *
    FROM (
        SELECT 0 AS priority, t.* FROM table1 AS t
         WHERE id IN (SELECT MAX(id) AS id FROM table1 GROUP BY DATE(submit))
  UNION ALL
        SELECT 1 AS priority, t.* FROM table1 AS t
         WHERE id NOT IN (SELECT MAX(id) AS id FROM table1 GROUP BY DATE(submit))
         ) AS results
  ORDER BY priority, submit
  LIMIT 1500

这将为您提供每个submit日期至少一行,然后是其余行,但不会超过1500.但是,它不会尝试平衡每个日期的行数。

答案 1 :(得分:0)

步骤1.数据表......

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table 
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,dt DATE NOT NULL
);

INSERT INTO my_table (dt) VALUES
('2014-07-28'),
('2014-07-29'),
('2014-08-01'),
('2014-08-01'),
('2014-08-02'),
('2014-08-03'),
('2014-08-05'),
('2014-08-05'),
('2014-08-05'),
('2014-08-05'),
('2014-08-07'),
('2014-08-07'),
('2014-08-09'),
('2014-08-10'),
('2014-08-10'),
('2014-08-10'),
('2014-08-11'),
('2014-08-13'),
('2014-08-13'),
('2014-08-13'),
('2014-08-13'),
('2014-08-13'),
('2014-08-13'),
('2014-08-14'),
('2014-08-14'),
('2014-08-15'),
('2014-08-17'),
('2014-08-17'),
('2014-08-18'),
('2014-08-18'),
('2014-08-18'),
('2014-08-19'),
('2014-08-19'),
('2014-08-21'),
('2014-08-21'),
('2014-08-21'),
('2014-08-21'),
('2014-08-22'),
('2014-08-23'),
('2014-08-25'),
('2014-08-25'),
('2014-08-26'),
('2014-08-26'),
('2014-08-26'),
('2014-08-27'),
('2014-08-28'),
('2014-08-29'),
('2014-08-29'),
('2014-08-29'),
('2014-08-29'),
('2014-08-29'),
('2014-08-30'),
('2014-08-31'),
('2014-08-31');

SELECT * FROM my_table;
+----+------------+
| id | dt         |
+----+------------+
|  1 | 2014-07-28 |
|  2 | 2014-07-29 |
|  3 | 2014-08-01 |
|  4 | 2014-08-01 |
|  5 | 2014-08-02 |
|  6 | 2014-08-03 |
|  7 | 2014-08-05 |
|  8 | 2014-08-05 |
|  9 | 2014-08-05 |
| 10 | 2014-08-05 |
| 11 | 2014-08-07 |
| 12 | 2014-08-07 |
| 13 | 2014-08-09 |
| 14 | 2014-08-10 |
| 15 | 2014-08-10 |
| 16 | 2014-08-10 |
...
...
| 44 | 2014-08-26 |
| 45 | 2014-08-27 |
| 46 | 2014-08-28 |
| 47 | 2014-08-29 |
| 48 | 2014-08-29 |
| 49 | 2014-08-29 |
| 50 | 2014-08-29 |
| 51 | 2014-08-29 |
| 52 | 2014-08-30 |
| 53 | 2014-08-31 |
| 54 | 2014-08-31 |
+----+------------+

步骤2.包含所有可想到的日期的日历实用程序表...(还有其他方法可以执行此操作,但是 - 异常 - 此问题需要在MySQL中进行,而不是在后处理中)< / p>

SELECT *
  FROM calendar
 WHERE dt BETWEEN '2014-07-28' AND '2014-09-02';
+------------+
| dt         |
+------------+
| 2014-07-28 |
| 2014-07-29 |
| 2014-07-30 |
| 2014-07-31 |
| 2014-08-01 |
| 2014-08-02 |
| 2014-08-03 |
| 2014-08-04 |
| 2014-08-05 |
| 2014-08-06 |
| 2014-08-07 |
| 2014-08-08 |
| 2014-08-09 |
| 2014-08-10 |
| 2014-08-11 |
| 2014-08-12 |
| 2014-08-13 |
| 2014-08-14 |
| 2014-08-15 |
| 2014-08-16 |
| 2014-08-17 |
| 2014-08-18 |
| 2014-08-19 |
| 2014-08-20 |
| 2014-08-21 |
| 2014-08-22 |
| 2014-08-23 |
| 2014-08-24 |
| 2014-08-25 |
| 2014-08-26 |
| 2014-08-27 |
| 2014-08-28 |
| 2014-08-29 |
| 2014-08-30 |
| 2014-08-31 |
| 2014-09-01 |
| 2014-09-02 |
+------------+
37 rows in set

步骤3.查询(保证每天至少一个结果,总体上不超过50个结果)

SELECT dt FROM 
(
SELECT a.dt
     , COALESCE(rank,0)
  FROM calendar a
  LEFT
  JOIN 
     ( SELECT x.dt,COUNT(*) rank
         FROM my_table x 
         JOIN my_table y 
           ON y.dt = x.dt 
          AND y.id <= x.id
        GROUP   
           BY x.id
     ) b
    ON b.dt = a.dt
 WHERE a.dt BETWEEN '2014-08-01' AND '2014-08-31'
 ORDER 
    BY rank,dt
 LIMIT 50
 )n
 ORDER BY dt; 
 +------------+
 | dt         |
 +------------+
 | 2014-08-01 |
 | 2014-08-01 |
 | 2014-08-02 |
 | 2014-08-03 |
 | 2014-08-04 |
 | 2014-08-05 |
 | 2014-08-05 |
 | 2014-08-05 |
 | 2014-08-06 |
 | 2014-08-07 |
 | 2014-08-07 |
 | 2014-08-08 |
 | 2014-08-09 |
 | 2014-08-10 |
 | 2014-08-10 |
 | 2014-08-10 |
 | 2014-08-11 |
 | 2014-08-12 |
 | 2014-08-13 |
 | 2014-08-13 |
 | 2014-08-13 |
 | 2014-08-14 |
 | 2014-08-14 |
 | 2014-08-15 |
 | 2014-08-16 |
 | 2014-08-17 |
 | 2014-08-17 |
 | 2014-08-18 |
 | 2014-08-18 |
 | 2014-08-18 |
 | 2014-08-19 |
 | 2014-08-19 |
 | 2014-08-20 |
 | 2014-08-21 |
 | 2014-08-21 |
 | 2014-08-21 |
 | 2014-08-22 |
 | 2014-08-23 |
 | 2014-08-24 |
 | 2014-08-25 |
 | 2014-08-25 |
 | 2014-08-26 |
 | 2014-08-26 |
 | 2014-08-27 |
 | 2014-08-28 |
 | 2014-08-29 |
 | 2014-08-29 |
 | 2014-08-30 |
 | 2014-08-31 |
 | 2014-08-31 |
 +------------+
 50 rows in set (0.00 sec)

答案 2 :(得分:-1)

也许这样的事情会疯狂吗?

SELECT * FROM
  (SELECT * FROM
    (SELECT * FROM table1 
      WHERE `submit` = '2014-08-01'
        LIMIT 48
    UNION SELECT * FROM table1 
      WHERE `submit` = '2014-08-02'
        LIMIT 48
    UNION SELECT * FROM table1 
      WHERE `submit` = '2014-08-03'
        LIMIT 48
    UNION SELECT * FROM table1 
      WHERE `submit` = '2014-08-04'
        LIMIT 48
    etc...
    )
  UNION SELECT * FROM Table1 
      WHERE `submit` >= '2014-08-01' AND `submit` <= '2014-08-31'
  )
order by `submit`
  LIMIT 1500