2017-10-13 81 views
2

我正在使用零件/摩托車裝備的Mysql數據庫,其中所有零件都鏈接到可以安裝的所有摩托車上。它看起來像這樣: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可在本田CBR1000安裝2008年至2013年
  • 部分#1001可在本田CBR600安裝從2008年到2009年,以及從2008年到2013年的本田CBR1000。

不幸的是,該表(它有〜650,000行)並不總是正確填寫。在這個例子中,你會發現下面的線條缺失:

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

由於部分#1001可以在HONDA_CBR1000安裝從2008年,2009年和2013年也可以安裝在「被遺忘的」年之間(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?你認爲這太慢了嗎?

感謝您的幫助!

+0

查看https://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very-simple- sql-query – Strawberry

回答

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' 

********************* EDIT 2 ********** ************************

所以這是將列出錯過的年份的查詢。你可以把整個查詢到一個INSERT語句

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 

年 - >子查詢產生年1950至2050年(如果你有兩年以上(2050年之後或1950年以前),那麼這必須改變)

我選擇每個產品編號的最小和最大年份之間的年份。然後用年表作爲參考,找到最小和最大年份之間的年份。

以上查詢的結果會給出最小值和最大值之間的所有年份。減去會給錯過的年份

+0

非常好的方法!不幸的是,我看到這個查詢很慢(對於我的問題提到的簡單查詢,2.5秒vs 0.2秒)。我想保持非常快速的結果的唯一方法是在數據庫中添加缺失的行。我可以創建一個包含所有缺失行的新表,並將其鏈接到「mytable」(使用part_number作爲外鍵)。這樣我保持「mytable」完好無損。你認爲一個查詢可以檢索所有缺少的行嗎? – max

+0

我編輯過,很多檢查會降低性能。這可能有助於提高性能。我在想一個查詢來查找你的缺失變量。我會很快發佈。 – Valli

+0

再次編輯添加一個查詢,將檢索所有缺少的行 – Valli

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表只是一個年份列表,因此您可以從其他表或通過創建派生表獲取它。子查詢只是獲取它的一種便捷方式。

+0

非常感謝Gordon。我嘗試了你的解決方案,但最後我選擇了另一個解決方案(正如我對Valli的評論中所解釋的),因爲這是獲得非常快速結果的最佳方法。儘管如此,爲了其他目的,我會記住您的代碼。再次感謝 – max

相關問題