【问题标题】:MySQL: Counting across many to many and one to many (and other stuff)MySQL:计数多对多和一对多(和其他东西)
【发布时间】:2017-11-27 03:35:31
【问题描述】:

我有一个包含许多表的 MySQL 数据库。与此问题相关的是:

TABLE: Schedule (For booking time on a machine)
       - SlotID (INTEGER - AUTO_INCREMENT - PRIMARY KEY)
       - SlotDate (VARCHAR)
       - SlotStart (INTEGER)
       - SlotStop (INTEGER)
       - UserID (INTEGER - FOREIGN KEY REFERENCES User.UserID)
       - OperatorID (INTEGER - FOREIGN KEY REFERENCES User.UserID)

TABLE: Treatment (Defines what the machine should do)
       - TreatmentID (INTEGER - AUTO_INCREMENT - PRIMARY KEY)
       - SOME OTHER BOOLEANS TO ACTIVATE EACH SENSOR (Irrelevant)

TABLE: ScheduleTreatment (Many to many relationships between Schedule & Treatment)
       - SlotID (INTEGER - FOREIGN KEY REFERENCES Schedule.SlotID)
       - TreatmentID (INTEGER - FOREIGN KEY REFERENCES Treatment.TreatmentID)

TABLE: Individual (each treatment will be applied to n different individuals)
       - IndID (INTEGER - AUTO_INCREMENT - PRIMARY KEY)
       - Active (BOOLEAN if 0 this should be ignored and not counted)
       - TreatmentID (INTEGER - FOREIGN KEY REFERENCES Treatment.TreatmentID)

TABLE: User (Table with user data)
       - UserID (INTEGER - AUTO_INCREMENT - PRIMARY KEY)
       - Username (VARCHAR)
       - Some other irrelevant fields

所以保留的机器插槽放在Schedule,要执行的操作放在Treatment,执行这些操作的个人(每个处理都对许多相同的个人进行统计)放在@987654325 @ 和 ScheduleTreatment 将插槽链接到应该在该插槽期间进行的不同处理(并且可以使用 TreatmentID 外键获得执行这些处理的个人。OperatorID 提供到用户的链接(不是插槽的所有者)将负责忽略该过程。

我想执行 Slot 预览,以便用户可以看到所有信息(因此查询应以 WHERE Schedule.UserID = ? 结尾),这意味着获取 Schedule.*、操作员的用户名和两个计数:一个有多少治疗(这个相对简单,ScheduleTreatment 和一个GROUP BY)和另一个有多少人(在所有分配的治疗中),我完全不知道怎么做。没有治疗的槽或有治疗但没有个体的槽也应该出现(对应的计数为 0)。

在我看来,这需要按两个不同的标准进行分组,但它看起来也可以在一个(比我更聪明)查询中完成。我已经设法分别完成它们,但不是在同一个查询中。这是一个获取 Treatment.* 和分配给它的所有个人的示例:

SELECT Treatment.TreatmentID, COUNT(Individual.TreatmentID) AS Individuals
FROM Treatment INNER JOIN Individual ON Individual.TreatmentID = 
Treatment.TreatmentID GROUP BY Individual.TreatmentID ORDER BY TreatmentID

提前致谢,

【问题讨论】:

标签: mysql join group-by many-to-many one-to-many


【解决方案1】:

我想执行一个 Slot 预览,以便用户可以看到所有信息(因此查询应该以 WHERE Schedule.UserID = ? 结尾)这意味着获取 Schedule.*

select Schedule.* from Schedule WHERE Schedule.UserID = ?

,运营商的用户名,

select Schedule.*, op.username as OperatorName 
from Schedule s
inner join User op on s.OperatorID = op.id
where Schedule.UserID = ?

还有两个计数:治疗次数之一(这个相对简单,使用 ScheduleTreatment 和 GROUP BY)

SELECT SlotID, COUNT(*) scount
FROM ScheduleTreatment
GROUP BY SlotID

还有多少人(在所有分配的治疗中),在这里我完全不知道如何。

SELECT SlotID, COUNT(*) icount
FROM ScheduleTreatment st
INNER JOIN Individual i on st.TreatmentID = i.TreatmentID 
WHERE i.actve <> 0
GROUP BY SlotID

没有治疗的槽或有治疗但没有个体的槽也应该出现(对应的计数为 0)。

SELECT Schedule.*, op.username as OperatorName , st.scount, i.icount
FROM Schedule s
INNER JOIN User op on s.OperatorID = op.id
LEFT JOIN (
           SELECT SlotID, COUNT(*) scount
           FROM ScheduleTreatment
           GROUP BY SlotID
           ) st on s.slotid = st.slotid
LEFT JOIN (
           SELECT SlotID, COUNT(*) icount
           FROM ScheduleTreatment st
           INNER JOIN Individual i on st.TreatmentID = i.TreatmentID 
           WHERE i.actve <> 0
           GROUP BY SlotID
           ) i on s.slotid = i.slotid
WHERE Schedule.UserID = ?

【讨论】:

  • 感谢您的帮助!我更正了一些拼写,但仍然收到 #1064 语法错误。问题是,我不太明白如何使用子查询。这是我尝试过的(略微)修改的版本:
  • SELECT Schedule.*, op.Username as OperatorName , st.scount, i.icount FROM Schedule s INNER JOIN User op on s.OperatorID = op.UserID LEFT JOIN ( SELECT SlotID, COUNT(*) as scount FROM ScheduleTreatment GROUP BY SlotID ) st on s.SlotID = st.SlotID LEFT JOIN ( SELECT SlotID, COUNT(i.*) as icount FROM ScheduleTreatment st INNER JOIN Individual i on st.TreatmentID = i.TreatmentID WHERE i.Active &lt;&gt; 0 GROUP BY SlotID ) i on s.SlotID = i.SlotID WHERE Schedule.UserID = 1
  • 我也尝试过子查询,它也有一些语法错误(或者可能是不同版本的 SQL,我在 MySQL 上):SELECT SlotID, COUNT(DISTINCT i.IndID) AS icount FROM ScheduleTreatment AS st INNER JOIN Individual as i on st.TreatmentID = i.TreatmentID WHERE i.Active &lt;&gt; 0 GROUP BY SlotID 这个可以解决问题,仍然可以不要把它们组合在一起。
  • 语法错误是 i.* 将其更改为 *。回到稍加修改的版本 2 cmets。在最后一个子查询中将Count(i.*) 更改为count(*) 或如果需要更改为COUNT(DISTINCT i.IndID)
猜你喜欢
  • 1970-01-01
  • 2015-10-25
  • 1970-01-01
  • 2011-03-09
  • 2011-10-16
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 2011-08-29
相关资源
最近更新 更多