2017-10-13 14 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 

だから、ということを意味:パーツ#1001はホンダCBR600にインストールすることができます

  • パーツ#1000は
  • 2008から2013年にホンダCBR1000にインストールすることができます。

残念ながら、テーブル(約650,000行)は必ずしも正しく充填されていませんでした。この例では、次の行が不足しているわかります:2008、2009年と2013年からHONDA_CBR1000にインストールすることができる部品で#1001は、またの間に「忘れられた」年でインストールすることができます

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

ので、 (2010年、2011年および2012年)。

だから、単純なクエリ:(現実には、パーツ#1001は、この自転車にもインストール可能である間)

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

は一部のみの#1000の行を取得します。平易な英語で

、私は

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 

*********************編集****************

へパフォーマンスを向上させる、********** EDIT 2 ********************* 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' 

、これを試すことができます***********************

だから、これは欠落している年を列挙するクエリです。 (あなたは()2050を超えるまたは1950年前に、より多くの年を持っている場合は、これを変更する必要があります)> 1950年から2050年までの年間発生サブクエリ - 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 

歳までにクエリ全体を置くことができます

各製品番号の最小年と最大年の間の年を選択しています。 yrsテーブルを基準として、最小年と最大年の間の年を求める。

上記のクエリの結果は、すべての年が最小から最大の間になることになります。マイナスは逃した年を与えるでしょう

+0

非常に良い方法!残念なことに、私はこのクエリがかなり遅い(私の質問に記載されている単純なクエリの2.5秒と0.2秒)を参照してください。私は非常に迅速な結果を維持する唯一の方法は、データベースに不足している行を追加することだと思います。すべての欠落した行を持つ新しいテーブルを作成し、それを "mytable"(part_numberを外部キーとして使用)にリンクすることができました。こうして私は「マイタブル」をそのまま保ちます。問合せで不足している行をすべて取り出すことができると思いますか? – max

+0

私は編集しましたが、多くのチェックでパフォーマンスが低下します。これにより、パフォーマンスが向上する可能性があります。あなたの欠けている変数を見つけるためのクエリを考えています。まもなく投稿します。 – Valli

+0

もう一度編集して、不足している行をすべて検索します。 – Valli

0

パーツとオートバイのすべての組み合わせを取得するための私のアプローチは、彼らはデータがない年です。

すべての年のすべての行を生成し、それを除外します。最初の部分はcross joinです。第2の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

ありがとう、ゴードン。私はあなたの解決策を試しましたが、最終的には非常に速い結果を得るための最良の方法だったので、別のものを選択しました(Valliへの私のコメントで説明したように)。私はあなたのコードを他の目的のために念頭に置いておきます。再度、感謝します – max

関連する問題