【问题标题】:GROUP BY, COUNT() in joined tables of MySQL queryMySQL 查询的联接表中的 GROUP BY、COUNT()
【发布时间】:2015-08-07 14:15:21
【问题描述】:

我希望在一组两个日期内按类别计算我的所有项目。 我有一个主表:

项目

+-----+-------------+------------------+
| uid |    name     | project_category |
+-----+-------------+------------------+
|   1 | Testproject |                1 |
|   2 | Anothertest |                2 |
|   3 | Fietspomp   |                1 |
|   4 | Caramba     |                1 |
+-----+-------------+------------------+

谁的类别存储在 project_category

+-----+-------------+
| uid |    name     |
+-----+-------------+
|   1 | Automotive  |
|   2 | Hospitality |
|   3 | Other       |
+-----+-------------+

但是,我的日期存储在下表中。每个项目可以有更多的日期(班次)。我只想找到每个项目的最早日期(班次):我需要过滤每个项目的开始日期(= 第一个班次)。

project_shift

+-----+-------------+------------+
| uid | project_uid |    date    |
+-----+-------------+------------+
|   1 |           1 | 2015-05-03 |
|   2 |           2 | 2015-05-02 |
|   3 |           2 | 2015-06-04 |
|   4 |           1 | 2015-03-08 |
|   5 |           1 | 2015-08-08 |
+-----+-------------+------------+

我一直在寻找高低,但我的计数总是一团糟。这是我尝试过的:

SELECT pc.name as category, p.name, count(p.uid)
FROM project p
INNER JOIN project_category pc ON pc.uid = p.project_category
INNER JOIN project_shift ps    ON ps.project_uid = p.uid AND ps.date BETWEEN "2015-01-01" AND "2015-08-08"
GROUP BY pc.uid

还有:

SELECT    pc.name as category, count(pc.uid) as amount
FROM      project p
LEFT JOIN project_category pc ON pc.uid = p.project_category
WHERE     (SELECT MIN(date) FROM project_shift ps WHERE ps.project_uid = p.uid LIMIT 1) BETWEEN :date_from AND :date_to
GROUP BY  pc.uid

最后一个接近了,但仍然太多了 29 个项目。

我在这里做错了什么?

编辑:所需结果如下(虚拟数据)

+-------------+--------+
|  category   | amount |
+-------------+--------+
| Automotive  |     70 |
| Hospitality |     22 |
| Other       |      2 |
+-------------+--------+

【问题讨论】:

  • 我不完全理解这个问题,但我认为它可以像使用COUNT DISTINCT 一样简单。尝试将您在上面发布的每个查询中的count(p.uid) 替换为count(distinct p.uid)

标签: mysql join count group-by


【解决方案1】:

您的查询似乎几乎正确。只是,您应该从中选择 project_category 和应该外部连接的项目(例如获取具有零项目的类别)。因此,您希望按类别计算项目(即p.uid)。

那么你的 LIMIT 子句就没有意义了。 MIN(date) 为您提供一条记录,其中包含项目的最短日期。这里不需要 LIMIT 子句。

SELECT    pc.name as category, count(p.uid) as amount
FROM      project_category pc 
LEFT JOIN project p ON p.project_category = pc.uid
WHERE     (SELECT MIN(date) FROM project_shift ps WHERE ps.project_uid = p.uid)
            BETWEEN :date_from AND :date_to
GROUP BY  pc.uid;

【讨论】:

    【解决方案2】:

    您还需要将项目表中的 project_category 包含在 group by 中:

    SELECT pc.name as category,  count(p.project_category)
    FROM project p, project_category pc, project_shift ps
    where pc.uid = p.project_category
    and ps.project_uid = p.uid
    and ps.date BETWEEN '1/1/2015' and '8/8/2015'
    group by pc.uid, p.project_category
    

    应该这样做。

    【讨论】:

    • 感谢您的回答,但您的查询给了我每个类别的太多结果。可能是因为每个项目有多个 project_shift 条目。你能再看看吗?
    【解决方案3】:

    试试这个:

    SELECT    pc.name as category, count(pc.uid) as amount
    FROM      project p
    INNER JOIN project_category pc ON pc.uid = p.project_category
    INNER JOIN
        (
            SELECT MIN(`date`) AS `date`, project_uid FROM project_shift 
            WHERE `date` BETWEEN :date_from AND :date_to
            GROUP BY project_uid
        ) AS ps ON (ps.project_uid = pc.uid) 
    GROUP BY  pc.uid
    

    【讨论】:

    • 谢谢,但这不会产生任何结果。我会进一步调查,看看我是否有问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 2014-04-28
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 2020-03-18
    相关资源
    最近更新 更多