2016-12-16 7 views
4

SQLクエリに問題があります。 私は何時間も試してみましたが、インターネットを検索しましたが、私が必要なものを見つけることはできません。SQLクエリ - CASEから新しい定義済みの値を数える

私はプライマリキーと外部キーとしてIDで接続された2つのテーブルを持っています。 2番目のテーブルの値はすべて特定のカテゴリを持ちます。 2番目のテーブルの各値は、異なるカテゴリにしかありません。 これをクエリ内で新しいカテゴリにソートする必要があります。複数の値が同じカテゴリを持つ可能性があります。 希望する出力は、0を含むそれぞれのカウントを持つこれらの新しいカテゴリのリストです。

サブテーブルなどとは異なる結合を試しましたが、望みの結果を得られませんでした。

meals: 
| id | name | food_id | 
+----+------+---------+ 
| 01 | Pete | 001  | 
| 02 | Anna | 002  | 
| 03 | Jim | 003  | 
| 04 | John | 002  | 
| 05 | Lucy | 003  | 

food: 
| id | name | 
+-----+--------+  
| 001 | Apple |  
| 002 | Banana | 
| 003 | Carrot | 
| 004 | Steak | 

マイクエリ:

SELECT  food.foodtype   AS foodtype, 
      COUNT(food.foodtype) AS amount 

FROM  (
      SELECT food.id   AS id 
        CASE WHEN food.name = 'Apple' THEN 'Fruit', 
         WHEN food.name = 'Banana' THEN 'Fruit', 
         WHEN food.name = 'Carrot' THEN 'Vegetable', 
         WHEN food.name = 'Steak' THEN 'Meat', 
        END    AS foodtype 
      FROM food 
      )      AS food 

INNER JOIN meals 
ON   meals.food_id = food.id 

GROUP BY food.foodtype 
(私はそれが理解できる願っています)

私のテーブル

は、残念ながら私はあなたにexcactテーブル/クエリを表示することができない私は、問題を再現してみました

このクエリの結果は、すべてのフードタイプが使用されているテーブルですが、未使用のフードタイプも0として表示する必要があります。

| foodtype | amount | 
+-----------+--------+ 
| Fruit  | 3  | 
| Vegetable | 2  | 

私が必要とする結果:私が持っていたもう一つのアイデア

| foodtype | amount | 
+-----------+--------+ 
| Fruit  | 3  | 
| Vegetable | 2  | 
| Steak  | 0  | 

、それでも私は必要となりません。

SELECT  CASE WHEN food.name = 'Apple' THEN 'Fruit', 
       WHEN food.name = 'Banana' THEN 'Fruit', 
       WHEN food.name = 'Carrot' THEN 'Vegetable', 
       WHEN food.name = 'Steak' THEN 'Meat', 
      END      AS foodtype 
      COUNT(meals.id)   AS amount 

FROM  meals 

RIGHT JOIN food 
ON   food.id = meals.food_id 

GROUP BY food.name 

マイ結果:

| foodtype | amount | 
+-----------+--------+ 
| Fruit  | 1  | 
| Fruit  | 2  | 
| Vegetable | 2  | 
| Meat  | 0  | 

私はそれが理解できる願っています何が必要なのか、誰かがこの問題で私を助けることができます。

+0

ある

;with cat as ( select * from ( values ('Apple' , 'Fruit' ), ('Banana', 'Fruit' ), ('Carrot', 'Vegetable'), ('Steak' , 'Meat' ) ) x (food_name, foodtype) ) select foodtype, count(m.id) amount from cat c left join food f on f.name = c.food_name left join meals m on m.food_id = f.id group by foodtype 

このアプローチを使用する - 私はあなたがあなたのfoodtypeたり、食べ物に基づいてカウントするかどうかを疑問に思いを。名? –

+0

正規化については、結合チェーンを構築できるように、food_typeテーブル(foodの親)が必要です。 –

答えて

1

はこれを確認してください。

  SELECT foodtype,COUNT(m.id) as amount 
      FROM   
      (
         SELECT id AS id, 
           name, 
           CASE WHEN name = 'Apple' THEN 'Fruit' 
            WHEN name = 'Banana' THEN 'Fruit' 
            WHEN name = 'Carrot' THEN 'Vegetable' 
            WHEN name = 'Steak' THEN 'Meat' 
           END    AS foodtype 

         FROM food 
         ) AS food 

      left JOIN meals m 
      ON   m.food_id = food.id 

      GROUP BY foodtype 
      order by foodtype 

出力

enter image description here

+0

これはうまくいくようです。私はすべてのデータを確認する必要がありますが、ありがとう! – vanils

0

IMHOデータベースを正規化して、フードタイプテーブルを追加する必要があります。あなたのデータベースを正規化した場合

構造は以下のようになります。

FOODTYPE (table) 
ID NAME 
001 Fruit 
002 Vegetables 
003 Meat 

FOOD (table) 
ID NAME FOODTYPE_ID 
001 Apple 001 
002 Banana 001 
003 Carrot 002 
004 Steak 003 

MEAL (Table) 
ID NAME FOOD_ID 
01 Pete 001 
02 Anna 002 
03 Jim 003 
04 John 002 
05 Lucy 003 

あなたのクエリになるでしょう:

SELECT ft.name, 
    (SELECT count(*) 
    FROM food f 
    JOIN meal m 
     ON f.id m.food_id 
    WHERE f.foodtype_id = ft.id) 
FROM foodtype ft 

いますが、できない場合は...

はこれを試してみてください:

select 
    x.foodtype, 
    (select COUNT(*) 
    from meal m 
    join food f 
     on m.food_id = f.id 
    where case 
     when f.name = 'Apple' or f.name = 'Banana' then 'Fruit' 
     when f.name = 'Carrot' then 'Vegetables' 
     when f.name = 'Steak' then 'Meat' 
    end = x.foodtype 
    ) 
from 
    (select distinct 
    case 
     when f.name = 'Apple' or f.name = 'Banana' then 'Fruit' 
     when f.name = 'Carrot' then 'Vegetables' 
     when f.name = 'Steak' then 'Meat' 
    end foodtype 
    from #food f) as x 
2

LEFT JOINを使用して、特定の食品タイプに属する食事を数えます。あなたの元のINNER JOINは結果セットから消えていく食事と一致しない食物タイプをもたらしました。

SELECT food.foodtype AS foodtype, 
     COUNT(meals.food_id) AS amount 
FROM 
(
    SELECT food.id AS id, 
      CASE WHEN food.name = 'Apple' THEN 'Fruit' 
       WHEN food.name = 'Banana' THEN 'Fruit' 
       WHEN food.name = 'Carrot' THEN 'Vegetable' 
       WHEN food.name = 'Steak' THEN 'Meat' 
      END AS foodtype 
    FROM food 
) AS food 
LEFT JOIN meals 
    ON meals.food_id = food.id 
GROUP BY food.foodtype 
+0

case文の構文はworngです – Mansoor

0
CREATE TABLE #meals 
    ([id] int, [name] varchar(4), [food_id] int) 
; 

INSERT INTO #meals 
    ([id], [name], [food_id]) 
VALUES 
    (01, 'Pete', 001), 
    (02, 'Anna', 002), 
    (03, 'Jim', 003), 
    (04, 'John', 002), 
    (05, 'Lucy', 003) 

CREATE TABLE #food 
    ([id] int, [name] varchar(6)) 
; 

INSERT INTO #food 
    ([id], [name]) 
VALUES 
    (001, 'Apple'), 
    (002, 'Banana'), 
    (003, 'Carrot'), 
    (004, 'Steak') 
; 


SELECT food.foodtype AS foodtype, 
     COUNT(meals.food_id) AS amount 
FROM 
(
    SELECT id AS id, 
      CASE WHEN name = 'Apple' THEN 'Fruit' 
       WHEN name = 'Banana' THEN 'Fruit' 
       WHEN name = 'Carrot' THEN 'Vegetable' 
       WHEN name = 'Steak' THEN 'Meat' 
      END AS foodtype 
    FROM #food 
) AS food 
FUll JOIN #meals meals 
    ON meals.food_id = food.id 
GROUP BY food.foodtype 
order by food.foodtype 

出力キーがcase発現およびleft joinによってグループにある

​​
0

DECLARE @meals TABLE (id INT, fid INT) 
DECLARE @food TABLE (id INT, name VARCHAR(MAX)) 

INSERT INTO @meals 
     (id, fid) 
VALUES (1, 1), 
     (2, 2), 
     (3, 3), 
     (4, 2), 
     (5, 3) 

INSERT INTO @food 
     (id, name) 
VALUES (1, 'apple'), 
     (2, 'banana'), 
     (3, 'carrot'), 
     (4, 'steak') 

SELECT CASE WHEN f.name = 'Apple' THEN 'Fruit' 
      WHEN f.name = 'Banana' THEN 'Fruit' 
      WHEN f.name = 'Carrot' THEN 'Vegetable' 
      WHEN f.name = 'Steak' THEN 'Meat' 
     END AS ft , 
     COUNT(m.ID) AS amount 
FROM @food f 
     LEFT JOIN @meals m ON f.id = m.fid 
GROUP BY CASE WHEN f.name = 'Apple' THEN 'Fruit' 
       WHEN f.name = 'Banana' THEN 'Fruit' 
       WHEN f.name = 'Carrot' THEN 'Vegetable' 
       WHEN f.name = 'Steak' THEN 'Meat' 
     END 
ORDER BY amount desc   

出力:

ft   amount 
Fruit  3 
Vegetable 2 
Meat  0 

共通テーブル式を使用して別のバリアント:

;WITH cte 
      AS (SELECT CASE WHEN f.name = 'Apple' THEN 'Fruit' 
          WHEN f.name = 'Banana' THEN 'Fruit' 
          WHEN f.name = 'Carrot' THEN 'Vegetable' 
          WHEN f.name = 'Steak' THEN 'Meat' 
         END AS ft , 
         m.id 
       FROM  @food f 
         LEFT JOIN @meals m ON f.id = m.fid 
      ) 
    SELECT ft , 
      COUNT(ID) AS amount 
    FROM cte 
    GROUP BY ft 
    ORDER BY amount DESC 
0

あなたがこれまでに行った作業を理解するために、最後のステップは簡単かもしれないもし、あなたが掲示中間結果が正しい場合にのみ "ベースデータセット "と呼ぶ。次に、あなたのfoodtypeオーバーのみグループ化が必要である:

SELECT 
x.foodtype, 
SUM(X.amount) AS amount 
FROM (
SELECT  CASE WHEN food.name = 'Apple' THEN 'Fruit', 
     WHEN food.name = 'Banana' THEN 'Fruit', 
     WHEN food.name = 'Carrot' THEN 'Vegetable', 
     WHEN food.name = 'Steak' THEN 'Meat', 
     END      AS foodtype 
     COUNT(meals.id)   AS amount 

FROM  meals 

RIGHT JOIN food 
ON   food.id = meals.food_id 

GROUP BY food.name 
) AS x 
GROUP BY x.foodtype 
; 

ヒント:私は私と一緒にお待ちくださいにStackOverflowの構文に新たなんだ;)

編集:私はあなたのように「肉」を必要とする提案していますその結果、あなたが書いた "ステーキ"ではありません。

0

私は、これは、出力あなたの2つの異なるアプローチ与える

foodtype amount 
Fruit  3 
Meat  0 
Vegetable 2 
+0

これは私が間違った値の肉(それは1と言うでしょうが、私は0を持っています) – vanils

+0

あなたが掲示したデータで0を返します – MtwStark

+0

鉱山の解決策は受け入れられた答えと同じですが、 'CASE EXPRESSION'と副問い合わせ。 – MtwStark

関連する問題