在子查询的结果集中计数

时间:2014-10-25 14:23:44

标签: sql postgresql

我的数据库中有以下关系:

Invoice                           InvoiceMeal
---------------------             ---------------------------
| InvoiceId | Total |             | Id | InvoiceId | MealId |
---------------------             ---------------------------
| 1         | 22.32 |             | 1  | 1         | 3      |
---------------------             ---------------------------
| 2         | 12.18 |             | 2  | 1         | 2      |
---------------------             ---------------------------
| 3         | 27.76 |             | 3  | 2         | 2      |
---------------------             ---------------------------

Meal                                            Type
-----------------------------------             -------------------
| Id     | Name          | TypeId |             | Id | Name       |
-----------------------------------             -------------------
| 1      | Hamburger     | 1      |             | 1  | Meat       |
-----------------------------------             -------------------
| 2      | Soja Beans    | 2      |             | 2  | Vegetarian |
-----------------------------------             -------------------
| 3      | Chicken       | 2      |
-----------------------------------

我想从数据库中查询的是InvoiceIdTotal所有Invoices,其中包含至少两个Meals,其中至少有一个Meals是} Type 素食。我有以下SQL查询,它可以工作:

SELECT 
   i."Id", i."Total"
FROM 
   public."Invoice" i
WHERE
   (SELECT COUNT(*)
   FROM public."InvoiceMeal" im
   WHERE im."InvoiceId" = i."Id" AND
                              (SELECT COUNT(*) 
                              FROM public."Meal" m, public."Type" t
                              WHERE im."MealId" = m."Id" AND
                              m."TypeId" = t."Id" AND 
                              g."Name" = 'Vegetarian') > 0
   ) >= 2;

我对此查询的问题是我无法轻易修改必须至少有一个vegetarien Meal的条件。例如,我希望能够将其改为至少两顿素食餐。如何通过查询实现此目的?

1 个答案:

答案 0 :(得分:3)

我会通过将表连接在一起并使用聚合来实现此目的。 having子句可以处理条件:

select i.Id, i.Total
from InvoiceMeal im join
     Invoice i
     on i.InvoiceId = im.InvoiceId join
     Meal m
     on im.mealid = m.mealid join
     Type t
     on m.typeid = t.typeid
group by i.Id, i.Total
having count(distinct im.mealid) >= 2 and
       sum(case when t.name = 'Vegetarian' then 1 else 0 end) > 0;

我也认为没有理由在列名称周围添加双引号。这只会使查询更难写和读。