Mysql:查询字段的最小值和最大值之间缺少的行

时间:2017-10-13 20:38:14

标签: mysql sql

我正在使用零件/摩托车配件Mysql数据库,其中所有零件都链接到可以安装的所有摩托车。它看起来像这样:

part_number motorcycle      year
1000        HONDA_CBR1000   2008
1000        HONDA_CBR1000   2009
1000        HONDA_CBR1000   2010
1000        HONDA_CBR1000   2011
1000        HONDA_CBR1000   2012
1000        HONDA_CBR1000   2013
1001        HONDA_CBR600    2008
1001        HONDA_CBR600    2009
1001        HONDA_CBR1000   2008
1001        HONDA_CBR1000   2009
1001        HONDA_CBR1000   2013

所以这意味着:

  • 零件#1000可以从2008年到2013年安装在本田CBR1000上
  • 零件#1001可以在2008年至2009年安装在本田CBR600上,在2008年至2013年安装在本田CBR1000上。

不幸的是,表(大约有650,000行)并不总是正确填充。在此示例中,您将注意到以下行缺失:

part_number motorcycle      year
1001        HONDA_CBR1000   2010
1001        HONDA_CBR1000   2011
1001        HONDA_CBR1000   2012

因为可以在2008年,2009年和2013年安装在HONDA_CBR1000上的部件#1001也可以在(2010年,2011年和2012年)之间的“被遗忘”年份安装。

所以简单的查询:

SELECT * FROM mytable WHERE motorcycle = 'HONDA_CBR1000' AND year = '2011'

只能检索部件#1000的行(实际上,部件#1001也可以安装在这辆自行车上)。

用简单的英语,我想像

这样的查询
SELECT * FROM mytable WHERE motorcycle = 'HONDA_CBR1000'
AND ("minimum year of part_number applicable to HONDA_CBR1000" <= '2011')
AND ("maximum year of part_number applicable to HONDA_CBR1000" >= '2011')

将检索所有结果(1000和1001)。

但是我怎么能在SQL中问这个?你认为它会太慢吗?

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

SELECT part_number, max(year), Min(year) 
  FROM mytable 
WHERE motorcycle = 'HONDA_CBR1000'
Group By part_number
Having Min(year) <= 2011
  And max(year) >= 2011

*********************编辑****************

为了提高性能,请试试这个, 1)

 SELECT part_number 
          FROM mytable t, 
               (Select part_number, Min(year) Minyear, max(year) Maxyear
                  FROM mytable
                Group BY part_number) t1
        WHERE t.motorcycle = 'HONDA_CBR1000'
           AND t.year Between MinYear and Maxyear
           AND t.year = '2011'

*********************编辑2 ************************ **********

所以这是将列出错过的年份的查询。您可以将整个查询放入插入语句

SELECT partsnumber ,  yrs.allyears
  FROM (Select max(year) maxyear, min(year) minyear, partsnumber
          FROM yourtable
      group by partsnumber) q1   
        (Select 1950+1+b+a*10 as allyears
           from (select 0 as a union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) a,
                 (select 0 as b union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) b) y
    Where yrs.allyears between maxyear and minyear

MINUS
SELECT partsnumber ,  yrs.allyears
 From yourtable

yrs - &gt;从1950年到2050年产生多年的子查询(如果你有更多的年份(超过2050年或1950年之前),那么这必须改变)

选择每个产品编号的最小和最大年份之间的年份。然后用yrs table作为参考,找到最小和最大年份之间的年份。

上述查询的结果将给出min和max之间的所有年份。减号将给出错过的年份

答案 1 :(得分:0)

这是我获得零件和摩托车的所有组合以及没有数据的年份的方法。

生成所有年份的所有行,然后过滤掉您拥有的行。第一部分使用cross join。第二个left join

select pm.part_number, pm.motorcycle, y.year
from (select part_number, motorcycle, min(year) as miny, max(year) as maxy
      from mytable
      group by part_number, motorcycle
     ) pm cross join
     (select distinct year
      from mytable
     ) y
     on y.year between pm.miny and pm.maxy left join
     mytable t
     on t.part_number = pm.part_number and t.motorcycle = pm.motorcycle and
        t.year = y.year
where y.year is null;

这假设所有年份都在你的桌子上,某处。 y表只是一个年份列表,因此您可以从另一个表或通过创建派生表获取它。子查询只是获取它的一种方便方法。