1

想象以下场景:公司的员工可以对任意问题(整数值)进行投票。

我有一个复杂的请求,我想获取五个信息:

  1. 公司的名称
  2. 每家公司的平均投票价值
  3. 在职员工人数
  4. 票数
  5. 参与(票数/员工人数)

SQL 查询只能获取当前用户所在公司的投票。

因此,在您看到表声明的摘录之后,我正在访问四个不同的表:

User
- id

Company
- id
- name

Employment
- user_id (FK User.id)
- company_id (FK Company.id)

Vote
- company_name
- vote_value
- timestamp

UserCompany通过Employment(n:m 关系,但需要是额外的表)相关。该表Vote不应通过 PK/FK 关系连接,但可以通过公司名称 ( Company.name = Vote.company_name) 与公司相关联。

我设法通过以下 SQL 查询正确地获取了除员工人数之外的所有信息:

SELECT
    c.name AS company,
    AVG(v.vote_value) AS value,
    COUNT(e.user_id) AS employees,
    COUNT(f.face) AS votes,
    (COUNT(e.user_id) / COUNT(v.vote_value)) AS participation
FROM Company c
JOIN Employment e ON e.company_id = c.id
JOIN User u ON u.id = e.user_id
JOIN Vote v
    ON v.company_name = c.name
    AND YEAR(v.timestamp) = :year
    AND MONTH(v.timestamp) = :month
    AND DAY(v.timestamp) = :day
WHERE u.id = :u_id
GROUP BY v.company_name, e.company_id

employee但是,该字段始终等于投票数,而不是获取正确数量的员工。(因此该participation值也是错误的。)

有没有办法在没有子查询1的查询中执行此操作?我必须进行哪些更改才能使查询获取正确数量的员工?

1我正在使用 Doctrine2 并尽量避免子查询,因为 Doctrine 不支持它们。我只是不想把它拉进教义讨论中。这就是我将这个主题分解为 SQL 级别的原因。

4

3 回答 3

1

试试这个——它将投票计算为一个子查询,将雇员计算为另一个子查询。

SELECT c.name,
ce.employee_count,
cv.vote_count,
cv.vote_count / ce.employee_count,
cv.vote_value
FROM 
(select company, count(*) AS 'employee_count' 
FROM employment GROUP BY company) ce
INNER JOIN company c
ON c.id = ce.company
INNER  JOIN 
(select company, AVG(vote_value) AS 'vote_value', count(*) as 'vote_count'
FROM vote v GROUP BY company) cv
ON c.id = cv.company
于 2013-10-02T21:55:20.397 回答
1

如果您想获取员工人数,那么问题是您仅按 1 名员工进行过滤:

WHERE u.id = :u_id

其次,请记住,如果您要计算员工数量并且您已进入投票分组级别,那么您当然将拥有等于投票数量的行数。所以你必须区分@Przem ...提到:

COUNT(DISTINCT e.user_id) AS employees,

这样,您将唯一地计算公司的员工人数(摆脱员工拥有的所有投票的重复员工 ID)。

正如您在评论中提到的:

它返回 1 作为员工人数

这是因为 where 条件迫使 1 名员工获得多票。distinct 只会计算由该where子句过滤的唯一 1 名员工,这就是为什么您只得到 1 名员工。但是,这是正确的结果(基于您的过滤条件)。

select子句中添加子查询也会让您获得正确的结果,但会牺牲性能。

于 2013-10-02T22:01:30.803 回答
0

好吧,我认为使用这样定义的查询,您应该在计算员工人数时添加DISTINCT关键字:

SELECT
    c.name AS company,
    AVG(v.vote_value) AS value,
    COUNT(DISTINCT e.user_id) AS employees,
    COUNT(f.face) AS votes,
    (COUNT(DISTINCT e.user_id) / COUNT(v.vote_value)) AS participation
FROM Company c
JOIN Employment e ON e.company_id = c.id
JOIN User u ON u.id = e.user_id
JOIN Vote v
    ON v.company_name = c.name
    AND YEAR(v.timestamp) = :year
    AND MONTH(v.timestamp) = :month
    AND DAY(v.timestamp) = :day
GROUP BY v.company_name, e.company_id;

不过,不确定在 MySQL 中是否可行。

编辑:正如@Mosty Mostacho 指出的那样,u.id 上的条件是问题所在,没有它并添加了 DISTINCT 关键字,查询返回正确的结果,我编辑了上面的查询。

于 2013-10-02T21:47:43.817 回答