0

大家好,我执行这个查询是为了得到一个表,其中有一些数据库信息的统计信息。我想初始化不存在的字段(因为查询是在不同的日期执行的,有时有一天什么都没有)所以我希望它返回 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
4

3 回答 3

1

假设tmp1你有你需要的数据,但有“差距”(根本没有数据的日子)你可以使用RIGHT JOINtmp1 到表tmp2day(我假设你在表中有这样的列tmp1)。所以tmp2只是几天的列表:

SELECT '2013-05-17' as day UNION SELECT '2013-05-18' UNION SELECT ...

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

于 2013-05-17T15:29:09.233 回答
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
于 2013-05-21T14:37:55.660 回答
0

SQL 擅长将现有实体分组,但不擅长“创建”实体本身。如果您也有非日期类别,我会建议一个通用数字表(实际上只是从 0 到几十万的数字),或者正如 Wiktor 建议的那样,它会时不时地填写一个日期表,并且在接下来的几年中以及程序运行以来的时间。

带日期表

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
;
于 2013-05-27T14:29:49.967 回答