如果没有结果,则将查询中的所有值初始化为0,并将top返回NULL

时间:2013-05-17 13:08:27

标签: mysql sql database

大家好我执行此查询以获取一个表格,其中包含一些数据库信息的统计信息。我想要初始化不存在的字段(因为查询是在不同的日期执行的,有时候会有一天什么都没有)所以我希望它返回0和NULL(在TOP列中)


SELECT
  SUM(IF(`TOP` = 'one',`Nb`,0)) as first_one,
  SUM(IF(`TOP` = 'two',`Nb`,0)) as second_one,
  SUM(IF(`TOP` = 'three',`Nb`,0)) as thrid_one,
  SUM(IF(`TOP` NOT IN ('three','two','one'),`Nb`,0)) as forth_one,
  GROUP_CONCAT(IF(`TOP` NOT IN ('three','two','one'),`TOP`,'') SEPARATOR '') as `OR`
FROM (
    SELECT 
        COUNT(*) as Nb,
        'one' as `TOP` 
    FROM 
        mytable 
    WHERE 
        TYPE = 'MSS' 
        AND YEAR(date) = YEAR(CURDATE()) 
        AND MONTH(date) = MONTH(CURDATE()) 
    UNION ALL
    SELECT 
        COUNT(*) as Nb,
        'two' as `TOP` 
    FROM 
        mytable 
    WHERE 
        TYPE = 'MSS' 
        AND S=0
        AND YEAR(date) = YEAR(CURDATE()) 
        AND MONTH(date) = MONTH(CURDATE()) 
    UNION ALL
    SELECT 
        COUNT(*) as Nb,
        'three' as `TOP` 
    FROM 
        mytable 
    WHERE 
        TYPE = 'MSS' 
        AND S<>0
        AND YEAR(date) = YEAR(CURDATE()) 
        AND MONTH(date) = MONTH(CURDATE()) 
    UNION ALL
    SELECT
      `Nb`,
      `TOP`
    FROM(
      SELECT 
        COUNT(*) as Nb ,
        `OR` as `TOP` 
      FROM 
        mytable 
      WHERE 
        TYPE = 'MSS'  
        AND YEAR(date) = YEAR(CURDATE()) 
        AND MONTH(date) = MONTH(CURDATE()) 
      GROUP BY 
        `OR` 
      ORDER BY 
         Nb DESC 
      LIMIT 1
    ) as tmp
)as tmp1

3 个答案:

答案 0 :(得分:1)

假设在tmp1中你需要数据但是有“空白”(根本没有数据的天数)你可以使用{{1} RIGHT JOIN tmp1到表tmp2 (我假设你在day表中有这样的列)。所以tmp1只是日期列表:

tmp2

如果您想提供数据库架构,我可以详细说明我的答案。

答案 1 :(得分:0)

您可以将每个子查询替换为:

SELECT
    IFNULL(tmp.Nb,0) as Nb,
    IFNULL(tmp.`TOP`, 'value') as `TOP`
FROM (    
   --subquery
) as tmp

第一个子查询的示例:

SELECT
    IFNULL(tmp.Nb,0) as Nb,
    IFNULL(tmp.`TOP`, 'one') as `TOP`
FROM (    
    SELECT 
        COUNT(*) as Nb,
        'one' as `TOP` 
    FROM 
        mytable 
    WHERE 
        TYPE = 'MSS' 
        AND YEAR(date) = YEAR(CURDATE()) 
        AND MONTH(date) = MONTH(CURDATE()) 
) as tmp

答案 2 :(得分:0)

SQL擅长将现有实体分组为类别,但不善于“创建”实体本身。如果您还有非日期类别,或者Wiktor建议使用日期表,那么我会建议使用通用数字表(实际上只是从0到数十万的数字),并且在接下来的几年里以及你的计划工作以来的时间。

使用日期表

list_dates (
     id int(11) not null primary key auto_increment, 
     dateval date not null
)

您可以从该表开始查询(当然,范围合理)并计算其他所有内容:

select list_dates.dateval as date, count(*) as cnt
from list_dates
left join actions on actions.actiontime >= (cast list_dates.date_val as datetime) 
     and actions.actiontime < (cast list_dates.date_val `interval 1 day as datetime) 
where list_dates.dateval between '$fromDate' and '$toDate'
group by list_dates.dateval
;

或以数字表编号

开头
select $fromDate + interval numbers.number day as date, count(*) as cnt
from numbers
left join actions 
on actions.actiontime >= (cast $fromDate + interval numbers.number day  as datetime) 
   and actions.actiontime < (cast $fromDate + interval (1 + numbers.number) day as datetime) 
where numbers.number >= 0 and numbers.number < $countDates
group by numbers.number
;

一天

如果你真的只想要那一天(今天)那么你当然可以使用匿名子选择 - 表,所以它变成了

select list_dates.dateval as date, count(*) as cnt
from ( select curdate() as dateval ) as list_dates
left join actions on actions.actiontime >= (cast list_dates.date_val as datetime) 
     and actions.actiontime < (cast list_dates.date_val `interval 1 day as datetime) 
where list_dates.dateval between '$fromDate' and '$toDate'
group by list_dates.dateval
;