実現

2011-12-14 1 views
1

Iは、2つのテーブルを有するデータベースを有する:実現

CREATE TABLE RecipeDB (
    RecipeID INT PRIMARY KEY AUTO_INCREMENT, 
    Name VARCHAR, 
    Recipe VARCHAR, 
    Origin VARCHAR, 
    Category VARCHAR, 
    Favoured BOOL); 

CREATE TABLE IngredientDB (
    RecipeID REFERENCES RecipeDB.RecipeID, 
    Ingredient VARCHAR, 
    Quantity VARCHAR); 

(1対多数のレシピおよび成分の関係)におけるIもActionScriptを有する

、私はingArr:成分文字列の配列を持っています。

今、私はここで、次のクエリを実現したいと思います:

1)(すべてのフィールド)のアレイからの食材のほとんどを持っている1つのレシピを選択します。複数のレコードに同じ量の一致がある場合は、マッチの数をレシピの成分の合計数で割り、最も高い比率のものを返します。一致するものがなければ何も返しません。

2)上記と同じですが、最も一致する10個のレシピが返され、等しい数の一致をチェックしません。結果を一致数でソートします。

SQLiteの中で、これらのクエリを作成する方法任意のアイデア?

答えて

1

(SQL文が下に提供SQLiteのためのものである)

  • だから、あなたはあなたが必要なもの、ほとんどの成分

に一致する上位10 recipeeを必要とする1秒間次のとおりです。

  • あなたのINGと一致する行を数えますredientリスト(オペレータでの使用)
  • 順子孫ために最高の数(4,3,2によって結果、...)
  • ように、SQL文が+ AS3AIRを使用して

    SELECT 
    r.RecipeId, COUNT(1) cnt, r.Name, r.Recipe, r.Origin, r.Category, r.Favoured 
    FROM 
    RecipeDB r 
    INNER JOIN IngredientDB i USING(RecipeID) 
    WHERE 
    i.Ingredient in ('ingr_1',..,'ingr_x') 
    GROUP BY 1 
    ORDER BY 2 DESC 
    LIMIT 10 
    

    のように見える10

によって制限結果をそれはそのようなものになることができます。

var sqls:SQLStatement = new SQLStatement() 
sqls.sqlConnection = YOUR SQL CONNECTION 

// your ingredient list 
var ingredients:Array = ['i2', 'i3', 'i4'] 

// use to build the in parameter array 
var inParams:Array = [] 

// fill parameter values 
for(var i:int = 0; i < ingredients.length; ++i) { 
inParams[i] = '?' 
sqls.parameters[i] = ingredients[i] 
} 

// build the query 
var qry:String = "SELECT r.RecipeId, COUNT(1) cnt, r.Name, r.Recipe, r.Origin,"+ 
"r.Category, r.Favoured FROM RecipeDB r INNER JOIN IngredientDB i USING(RecipeID)"+ 
"WHERE i.Ingredient in (" + inParams.join(',') + ") GROUP BY 1 "+ 
"ORDER BY 2 DESC LIMIT 10" 

// set the query 
sqls.text = qry 

//execute 
sqls.execute() 

  • そして、上記のように最初の同じ考えのためではなく、あなたが必要なもの

総一致/の間の比率を提供するために、recipeeにも、すべての成分の存在をカウントする必要がある:

  • カウント(IN演算子を使用)をお使いの成分リストと一致する行
  • で最高の試合
  • 制限の結果を得るすべての合計成分
  • 除算前回のカウントによってランクを作りますクエリのように書くことができる最初の例と同じロジックを使用して

    SELECT 
    i1.RecipeId, (cast(rs.cnt as real)/cast (COUNT(1) as real)) rank, 
    rs.Name, rs.Recipe, rs.Origin, rs.Category, rs.Favoured 
    FROM 
    IngredientDB i1 
    INNER JOIN (
        SELECT 
        r.RecipeId, COUNT(1) cnt, r.Name, r.Recipe, r.Origin, r.Category, r.Favoured 
        FROM 
        RecipeDB r 
        INNER JOIN IngredientDB i USING(RecipeID) 
        WHERE 
        i.Ingredient in ('ingr_1',..,'ingr_x') 
        GROUP BY 1 
    ) rs USING (RecipeId) 
    GROUP BY 1 
    ORDER BY 2 DESC 
    LIMIT 1 
    

だからSQL文がどのように見えるの魅力のような

var ingredients:Array = ['i2', 'i3', 'i4'] 
var inParams:Array = [] 
for(var i:int = 0; i < ingredients.length; ++i) { 
inParams[i] = '?' 
sqls.parameters[i] = ingredients[i] 
} 

var qry:String = "SELECT i1.RecipeId, (cast(rs.cnt as real)/cast (COUNT(1) as real)) rank,"+ 
"rs.Name, rs.Recipe, rs.Origin, rs.Category, rs.Favoured "+ 
"FROM IngredientDB i1 INNER JOIN ("+ 
"SELECT r.RecipeId, COUNT(1) cnt, r.Name, r.Recipe, r.Origin, r.Category, r.Favoured "+ 
"FROM RecipeDB r INNER JOIN IngredientDB i USING(RecipeID) "+ 
"WHERE i.Ingredient in (" + inParams.join(',') + ") GROUP BY 1) rs USING (RecipeId) "+ 
"GROUP BY 1 ORDER BY 2 DESC LIMIT 1" 
+0

作品、ありがとうございました。 – kyooryu

0

クエリはわずかに調整することができますが、以下のT-SQLは、あなたが探している答えをかなり読みやすい方法で示しています。

BEGIN 
-- setup test 
DECLARE @one TABLE(id INT, name VARCHAR(10)) 
DECLARE @many TABLE(pid INT, name VARCHAR(10)) 
INSERT INTO @one VALUES 
    (1, 'AAA'), 
    (2, 'BBB'), 
    (3, 'CCC') 
INSERT INTO @many VALUES  
    (1, 'x'),(1, 'y'),(1, 'z'), 
    (2, 'x'),(2, 'y'), 
    (3, 'z') 
-- 
-- WHERE m.name IN ('x', 'y') 
-- 'x', 'y' represent your list of ingrediants 
-- answer 1 
SELECT * FROM @one WHERE id = (
    SELECT TOP 1 x.id FROM (
     SELECT o.id, COUNT(o.id) 'match', (SELECT COUNT(*) FROM @many WHERE pid=o.id) 'total' FROM @one o 
      INNER JOIN @many m ON o.id = m.pid 
      WHERE m.name IN ('x', 'y', 'z') 
      GROUP BY o.id 
    ) as x ORDER BY x.match DESC, x.match/x.total DESC 
) 
-- answer 2 
SELECT * FROM @one WHERE id IN (
    SELECT TOP 10 x.id FROM (
     SELECT o.id, COUNT(o.id) 'match' FROM @one o 
      INNER JOIN @many m ON o.id = m.pid 
      WHERE m.name IN ('x', 'y') 
      GROUP BY o.id 
    ) as x ORDER BY x.match DESC 
) 
END