如何使用Union all查询获取不在表中的记录?

时间:2013-03-12 06:01:14

标签: mysql sql database

我在MYSQL数据库中有一个a_ad_display表,格式如下

╔═════════════╦═════════╦═════════╦═════════════════════╗
║ addisplayId ║ restId  ║ clicked ║     displaytime     ║
╠═════════════╬═════════╬═════════╬═════════════════════╣
║          1  ║  20707  ║      0  ║ 2013-03-07 10:50:55 ║
║          2  ║  20707  ║      1  ║ 2013-03-07 10:55:55 ║
║          3  ║  20711  ║      1  ║ 2013-03-08 12:50:55 ║
║          4  ║  20712  ║      1  ║ 2013-03-08 01:50:55 ║
║          5  ║  20707  ║      1  ║ 2013-03-08 10:50:55 ║
║          6  ║  20708  ║      1  ║ 2013-03-09 12:50:55 ║
║          7  ║  20707  ║      1  ║ 2013-03-09 09:50:55 ║
║          8  ║  20708  ║      0  ║ 2013-03-10 10:50:55 ║
║          9  ║  20708  ║      0  ║ 2013-03-11 11:50:55 ║
║         10  ║  20707  ║      0  ║ 2013-03-11 12:50:55 ║
╚═════════════╩═════════╩═════════╩═════════════════════╝

现在我想要的是用最近7天的数据来获取restId的记录

如果当前日期是2013-3-12,那么我想显示2013-3-5至2013-3-11的数据

     DISPLAY TIME                   CLICKED     count of row(impression)
March, 05 2013 00:00:00+0000            0       0             
March, 06 2013 00:00:00+0000            0       0
March, 07 2013 00:00:00+0000            1       2
March, 08 2013 00:00:00+0000            1       1
March, 09 2013 00:00:00+0000            1       1
March, 10 2013 00:00:00+0000            1       1
March, 11 2013 00:00:00+0000            0       1

我想忽略计时..只想在明确记录日期的同时专注于日期 我想用restId = 10707获取记录,其中包含该表中该日期的行总数以及该日期的点击总和,如果表格中没有记录上周日期的任何日期,那么它应打印该日期并在点击时打印0,在行计数列中打印0。

我在SQL小提琴中创建了一个虚拟表,并且还应用了这个查询但它没有工作......所以任何人都可以指导我...我知道它非常复杂,但是如果你对我的问题有任何疑问..然后会告诉你从你这边得到一个解决方案......

以下是我的查询没有提供正确的数据

select
  displaytime,
  sum(impression) as clicked,
  (count(impression) -1) as impressions
from (
  select
    displaytime,
    a_ad_display.clicked as impression
  from
    a_ad_display
  where
    a_ad_display.displaytime
  BETWEEN
    date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -6 day)
    AND
    CONVERT_TZ(CURDATE( ),'+00:00','-11:00')
    and
    restId=10708
    group by
      a_ad_display.displaytime
    union distinct
    select
      CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), 0
    union distinct
    select
      date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -1 day), 0
    union distinct
    select
      date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -2 day), 0
    union distinct
    select
      date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -3 day), 0
    union distinct
    select
      date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -4 day), 0
    union distinct
    select
      date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -5 day), 0
    union distinct
    select
      date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -6 day), 0
) as x
group by
  date(displaytime)
order by
  displaytime

请忽略代码CONVERT_TZ(CURDATE( ),'+00:00','-11:00'),因为它只是将我的日期从utc转换为用户时区...

这是我的sql小提琴链接 http://sqlfiddle.com/#!2/73f07/1

4 个答案:

答案 0 :(得分:2)

此查询应显示正确的数据。不是一个非常“干净”的解决方案。如果您真的想要包含没有数据的日期,则应该用日历表替换这些联合。

SELECT IFNULL(z.displaytime, x.displaytime), IFNULL(z.clicked, 0), IFNULL(z.count, 0)  FROM

  (select
    date(CONVERT_TZ(CURDATE( ),'+00:00','-11:00')) AS 'displaytime', 0 AS 'Clicked', 0 AS 'count of row(impression)'
  union distinct
  select
    date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -1 day)), 0, 0
  union distinct
  select
    date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -2 day)), 0, 0
  union distinct
  select
    date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -3 day)), 0, 0
  union distinct
  select
    date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -4 day)), 0, 0
  union distinct
  select
    date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -5 day)), 0, 0
  union distinct
  select
    date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -6 day)), 0, 0) AS x

LEFT JOIN

  (SELECT
    DATE(displaytime) AS 'displaytime',
    MAX(clicked) AS 'Clicked',
    COUNT(*) AS 'Count'
  FROM 
    a_ad_display
  WHERE (
    displaytime BETWEEN date_add(CURDATE(), interval -6 day) AND CURDATE()
  ) AND restId = 10707 
  GROUP BY DATE(displaytime)) AS z
ON x.displaytime = z.displaytime

答案 1 :(得分:1)

可能有一种更清洁的方式,但这应该有用......

select
  displaytime,
  sum(clicked) as clicked,
  sum(impressions) as impressions
from (
select
  displaytime,
  clicked,
  impressions
from (
select
  date(displaytime) as displaytime,
  sum(impression) as clicked,
  sum(legit) as impressions
from (
  select
    displaytime,
    a_ad_display.clicked as impression,
  1 as legit
  from
    a_ad_display
  where
    a_ad_display.displaytime
  BETWEEN
    date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -6 day)
    AND
    CONVERT_TZ(CURDATE( ),'+00:00','-11:00')
    and
    restId=10708
) as x
group by
  date(displaytime)
) y
union distinct
    select
      date(CONVERT_TZ(CURDATE( ),'+00:00','-11:00')), 0, 0
    union distinct
    select
      date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -1 day)), 0, 0
    union distinct
    select
      date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -2 day)), 0, 0
    union distinct
    select
      date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -3 day)), 0, 0
    union distinct
    select
      date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -4 day)), 0, 0
    union distinct
    select
      date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -5 day)), 0, 0
    union distinct
    select
      date(date_add(CONVERT_TZ(CURDATE( ),'+00:00','-11:00'), interval -6 day)), 0, 0
) z
group by
  displaytime
order by
  displaytime

答案 2 :(得分:1)

restID 20707的其他一些解决方案。对于2013-03-10,没有restID 20707的记录。

查询 SQLFIDDLEExample

SELECT d.Date,
(SELECT CASE WHEN COUNT(clicked) >0 THEN 1 ELSE 0 END
FROM a_ad_display
WHERE DATE(displaytime) = d.Date 
AND clicked = 1
AND restId  = 20707  ) Clicked,
(SELECT COUNT(*)
FROM a_ad_display
WHERE DATE(displaytime) = d.Date 
AND restId  = 20707  ) 'count of row'
FROM 
(SELECT a.Date
FROM
  (SELECT curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY AS Date
   FROM
     (SELECT 0 AS a
      UNION ALL SELECT 1
      UNION ALL SELECT 2
      UNION ALL SELECT 3
      UNION ALL SELECT 4
      UNION ALL SELECT 5
      UNION ALL SELECT 6
      UNION ALL SELECT 7
      UNION ALL SELECT 8
      UNION ALL SELECT 9) AS a CROSS
   JOIN
     (SELECT 0 AS a
      UNION ALL SELECT 1
      UNION ALL SELECT 2
      UNION ALL SELECT 3
      UNION ALL SELECT 4
      UNION ALL SELECT 5
      UNION ALL SELECT 6
      UNION ALL SELECT 7
      UNION ALL SELECT 8
      UNION ALL SELECT 9) AS b CROSS
   JOIN
     (SELECT 0 AS a
      UNION ALL SELECT 1
      UNION ALL SELECT 2
      UNION ALL SELECT 3
      UNION ALL SELECT 4
      UNION ALL SELECT 5
      UNION ALL SELECT 6
      UNION ALL SELECT 7
      UNION ALL SELECT 8
      UNION ALL SELECT 9) AS c) a
where a.Date >= '2013-01-01' and a.Date < curdate()) d
WHERE d.Date >= date_add(curdate(), INTERVAL -7 DAY)
ORDER BY d.Date

结果:

|                         DATE | CLICKED | COUNT OF ROW |
---------------------------------------------------------
| March, 05 2013 00:00:00+0000 |       0 |            0 |
| March, 06 2013 00:00:00+0000 |       0 |            0 |
| March, 07 2013 00:00:00+0000 |       1 |            2 |
| March, 08 2013 00:00:00+0000 |       1 |            1 |
| March, 09 2013 00:00:00+0000 |       1 |            1 |
| March, 10 2013 00:00:00+0000 |       0 |            0 |
| March, 11 2013 00:00:00+0000 |       0 |            1 |

答案 3 :(得分:0)

看看这个问题:

它几乎与你正在做的事情相同