想象一下以下情况:公司的员工可以对任意问题(整数值)进行投票。
我有一个复杂的请求,我想要获取五个信息:
SQL查询只能获取当前用户所使用的公司的投票。
因此,我会访问四个不同的表,然后您会看到表声明的摘录:
User
- id
Company
- id
- name
Employment
- user_id (FK User.id)
- company_id (FK Company.id)
Vote
- company_name
- vote_value
- timestamp
User
和Company
与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级别。
答案 0 :(得分: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
答案 1 :(得分:1)
如果您想获取员工人数,那么问题是您只过滤了一名员工:
WHERE u.id = :u_id
其次,请记住,如果您想计算员工数量并且您已进入投票分组级别,那么当然您的行数将等于投票数量。所以你必须将其统计为@Przem ...提到:
COUNT(DISTINCT e.user_id) AS employees,
通过这种方式,您将对公司的员工进行唯一计算(为员工的所有投票取消重复的员工ID)。
正如你在评论中提到的那样:
它返回1作为员工计数
这是因为迫使1名员工获得多票的条件。 distinct将仅计算由where
子句过滤的唯一1名员工,这就是您只得到1的原因。但是,这是正确的结果(基于您的过滤条件)。
在select
子句中添加子查询也可以获得正确的结果,但会牺牲性能。
答案 2 :(得分: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关键字,查询将返回正确的结果并编辑上述查询。