4

私はPostgreSQLを使用しています。人、レシピ、材料の3つのフィールドを持つテーブルがあります

person = creator of the recipe
recipe = the recipe
ingredient = one of the ingredients in the recipe

人参をレシピに追加したときはいつでも、その人は同じレシピに塩も追加したに違いないという結果になるクエリを作成したいと考えています。

複数の人がレシピを作成した可能性があります。その場合、材料を追加した人が材料を追加したことでクレジットされます。同じ人でも、その成分が複数回使用されることがあります。

このテーブルの場合:

person1, rec1, carrot
person1, rec1, salt
person1, rec1, salt
person1, rec2, salt
person1, rec2, pepper
person2, rec1, carrot
person2, rec1, salt
person2, rec2, carrot
person2, rec2, pepper
person3, rec1, sugar
person3, rec1, carrot

次に、この結果が必要です: person1

にんじんを加えるたびに塩も加えているのはこの人だけだからです。

「結果に影響を与えるのはニンジンだけです。レシピの 1 つに少なくとも 1 つのニンジンを追加した人のみが必要ですが、追加した同じレシピのすべてに塩を追加していない人は望んでいません。ニンジンと.申し訳ありませんが、それ以上明確に説明することはできません.

4

3 に答える 3

1

これはどう:

   SELECT DISTINCT person
     FROM tableName
    WHERE ingredient IN('carrot', 'salt')
 GROUP BY person, recipe
   HAVING SUM(CASE WHEN ingredient = 'carrot' THEN 1 ELSE -1 END) <= 0 
          AND
          COUNT(DISTINCT ingredient) > 1;

私は PostgreSql を使った経験があまりないことを認めますが、クエリはこのSQL Fiddleで必要な結果を提供するようです (最初のものを提供してくれた @JohnWoo の功績による)。

回答を更新しました。salts一部のレシピのみが正当なものとしてユーザーを返す前に。2 番目のHAVING句は、そのようなケースを除外します。

更新: 前のクエリは、ルール (「追加されたニンジンごとに塩も追加する」) に従う少なくとも 1 つのレシピを持つすべての所有者を返しました。しかし、実際には、すべてのレシピがルールに従っているものが必要です。したがって、クエリは次のようになります...

SELECT DISTINCT person 
  FROM tableName
 WHERE person NOT IN (   
     SELECT person
       FROM tableName
      WHERE ingredient IN('carrot', 'salt')
   GROUP BY person, recipe
     HAVING SUM(CASE WHEN ingredient = 'carrot' THEN 1 ELSE -1 END) > 0
 );

遊ぶSQLフィドル。

于 2012-10-31T17:33:37.890 に答える
0

これは、関係除算問題のバリエーションのようです。

ダブルネストNOT EXISTSソリューション:

SELECT DISTINCT person
FROM tableName AS t
WHERE NOT EXISTS
      ( SELECT *
        FROM tableName AS chosen
        WHERE chosen.ingredient = 'carrot'
          AND chosen.person = t.person
          AND NOT EXISTS
              ( SELECT *
                FROM tableName AS required
                WHERE required.ingredient = 'salt'
                  AND required.recipe = chosen.recipe
                  AND required.person = chosen.person
              ) 
      ) ;

そしてJOIN

SELECT DISTINCT 
    t.person
FROM 
        tableName AS t
    LEFT JOIN
            tableName AS chosen
        LEFT JOIN
            tableName AS required
          ON  required.ingredient = 'salt'
          AND required.recipe = chosen.recipe
          AND required.person = chosen.person
      ON  chosen.ingredient = 'carrot'
      AND chosen.person = t.person
      AND required.ingredient IS NULL
WHERE
    chosen.ingredient IS NULL ;
于 2012-10-31T18:27:08.630 に答える
0

試す:

SELECT person from
(SELECT person, recipe, COUNT(DISTINCT ingredient) ingredients
 FROM tableName
 WHERE ingredient IN ('salt', 'carrot')
 GROUP BY person, recipe
 HAVING MAX(CASE WHEN ingredient = 'carrot' THEN 1 END) = 1) p
group by person
HAVING MIN(ingredients) = 2
于 2012-10-31T17:25:07.000 に答える