使用嵌套查询与COUNT函数。

huangapple go评论82阅读模式
英文:

Using nested queries with COUNT function

问题

以下是您的翻译内容:

我正在使用一个SQL表来跟踪每天为学生提供的餐点数量。该表的结构如下:

学生ID 餐点日期 餐点类型
1 2023-05-21 1
2 2023-05-21 1
1 2023-05-21 2
2 2023-05-21 2
1 2023-05-22 1
1 2023-05-23 3

餐点类型列指定了餐点的类型:

  • 1 = 早餐
  • 2 = 午餐
  • 3 = 晚餐

因此,每个学生每天最多可以有3条记录。

现在,我正在尝试使用表格"Meals"中的数据创建发票。为此,我需要一个SQL查询,该查询生成给定月份中每天的早餐、午餐和晚餐的总数。基于上面显示的表格,查询应该类似于这样:

餐点日期 早餐 午餐 晚餐
2023-05-21 2 2 0
2023-05-22 1 0 0
2023-05-23 0 0 1

我假设嵌套查询是最佳方法,所以我已经做到了这一点:

SELECT MealDate, BreakfastCount, LunchCount, DinnerCount FROM 
(
	SELECT MealDate, LunchCount, DinnerCount, COUNT(*) AS "BreakfastCount" FROM 
	(
		SELECT MealDate, MealType, DinnerCount, COUNT(*) AS "LunchCount" FROM
        (
			SELECT MealDate, MealType, COUNT(*) AS "DinnerCount" FROM Meals
            WHERE MealType=3 AND MealDate LIKE '2023-05-%'
            GROUP BY MealDate
        ) Dinners
        WHERE MealType=2 AND MealDate LIKE '2023-05-%'
        GROUP BY MealDate
	) Lunches
    WHERE MealType=1 AND MealDate LIKE '2023-05-%'
    GROUP BY MealDate
) Breakfasts
GROUP BY MealDate

问题是,结果总是为空。我如何使它工作?单独的查询产生了预期的结果,但嵌套却破坏了它。我怀疑与WHERE子句中的餐点类型有关,但我不知道如何限制COUNT(*)函数到特定的餐点类型。

英文:

I am using an SQL table to keep track of the number of meals given to students every day. The table is structured as follows:

ID_Student MealDate MealType
1 2023-05-21 1
2 2023-05-21 1
1 2023-05-21 2
2 2023-05-21 2
1 2023-05-22 1
1 2023-05-23 3

The MealType columns specifies the type of meal:

  • 1 = Breakfast
  • 2 = Lunch
  • 3 = Dinner

Individual students can therefore have up to 3 records for each day.

I am now trying to create an invoice using the data in the table "Meals". For that, I need an SQL query that generates the total number of breakfasts, lunches and dinners for each day in a given month. Based on the table shown above it should look something like this:

MealDate Breakfasts Lunches Dinners
2023-05-21 2 2 0
2023-05-22 1 0 0
2023-05-23 0 0 1

I assume nested queries are the best approach here, so this is how far I've got:

SELECT MealDate, BreakfastCount, LunchCount, DinnerCount FROM 
(
	SELECT MealDate, LunchCount, DinnerCount, COUNT(*) AS "BreakfastCount" FROM 
	(
		SELECT MealDate, MealType, DinnerCount, COUNT(*) AS "LunchCount" FROM
        (
			SELECT MealDate, MealType, COUNT(*) AS "DinnerCount" FROM Meals
            WHERE MealType=3 AND MealDate LIKE '2023-05-%'
            GROUP BY MealDate
        ) Dinners
        WHERE MealType=2 AND MealDate LIKE '2023-05-%'
        GROUP BY MealDate
	) Lunches
    WHERE MealType=1 AND MealDate LIKE '2023-05-%'
    GROUP BY MealDate
) Breakfasts
GROUP BY MealDate

Problem is, the result is always empty. How can I make this work? The individual queries by themselves produce the expected results, but the nesting breaks it. I have a suspicion it has to do with the MealTypes in the WHERE clauses, but I don't know how else to restrict the COUNT(*) function to the specific meal type.

答案1

得分: 1

你的方法不错,虽然需要稍作调整才能使其正常工作。首先,将条件从WHERE子句移到聚合函数中(条件聚合)。然后,你会注意到,你总是在相同的字段上进行分组:你可以将所有计数聚合放在一个查询中。

如果你想筛选记录为2023年5月,而不是使用LIKE,最好使用日期函数(例如YEARMONTH),或者使用日期比较和月初进行比较。

SELECT MealDate, 
       COUNT(CASE WHEN MealType = 1 THEN ID_Student END) AS Breakfasts,
       COUNT(CASE WHEN MealType = 2 THEN ID_Student END) AS Lunches,
       COUNT(CASE WHEN MealType = 3 THEN ID_Student END) AS Dinners
FROM tab
WHERE YEAR(MealDate) = 2023 AND MONTH(MealDate) = 5
GROUP BY MealDate;

输出

MealDate Breakfasts Lunches Dinners
2023-05-21 2 2 0
2023-05-22 1 0 0
2023-05-23 0 0 1

在此查看演示链接

英文:

Your approach is good, although shall be tweaked a little to make it working. First move your conditions from the WHERE clauses to the aggregate functions (conditional aggregation). Then as you notice, you're grouping always on the same field: you can pull all your count aggregates in a single query.

If you want to filter your records to be on May 2023, instead of LIKE, it would be better to use date functions (like YEAR and MONTH), or use date comparison with the first of the month.

SELECT MealDate, 
       COUNT(CASE WHEN MealType = 1 THEN ID_Student END) AS Breakfasts,
       COUNT(CASE WHEN MealType = 2 THEN ID_Student END) AS Lunches,
       COUNT(CASE WHEN MealType = 3 THEN ID_Student END) AS Dinners
FROM tab
GROUP BY MealDate
WHERE YEAR(MealDate) = 2023 AND MONTH(MealDate) = 5
# WHERE MealDate BETWEEN '2023-05-01' AND '2023-06-01'

Output:

MealDate Breakfasts Lunches Dinners
2023-05-21 2 2 0
2023-05-22 1 0 0
2023-05-23 0 0 1

Check the demo here.

答案2

得分: 0

你可以使用条件聚合来完成,如下所示:

select MealDate, COUNT(CASE WHEN MealType = 1 THEN ID_Student END) AS 早餐,
                 COUNT(CASE WHEN MealType = 2 THEN ID_Student END) AS 午餐,
                 COUNT(CASE WHEN MealType = 3 THEN ID_Student END) AS 晚餐
from mytable
group by MealDate

示例在这里

英文:

You can do it using the conditional aggregation as follows :

select MealDate, COUNT(CASE WHEN MealType = 1 THEN ID_Student END) AS Breakfasts,
                 COUNT(CASE WHEN MealType = 2 THEN ID_Student END) AS Lunches,
                 COUNT(CASE WHEN MealType = 3 THEN ID_Student END) AS Dinners
from mytable
group by MealDate

Demo here

huangapple
  • 本文由 发表于 2023年5月21日 22:18:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76300357.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定