【问题标题】:Sql - struggling with count/having query based on several joinsSql - 努力计算/基于多个连接进行查询
【发布时间】:2010-09-18 10:05:40
【问题描述】:

我正在努力让我的查询正常工作。基本上,它应该做的只是返回尚未填补的空缺。例如,一个空缺可以有 5 个预定限制。要填补这个限制,它需要混合 5 个有效或待定预订,或者只是 5 个有效或 5 个待定预订。

当客户接受时,待定预订将变为活动状态。

提供我的设置的基本架构可能会有所帮助:-

**tbl.vacancies:**
vacancy_id
job_category_id
business_unit_id
start_date
publication_date
end_date
limit - how many bookings it will accept

**tbl.bookings**
booking_id
candidate_id
vacancy_id
booking_status_id
user_id
date

**btl.booking_status**
id
user_id
booking_status_type_id
date

**tbl.booking_status_type**
id (1,2,3,4)
name (pending, active, rejected, revoked)

当我在 job_category、business_unit、candidate、booking_status 和 booking_status_type 表之间创建内部联接时,我的查询在显示所有空缺时工作正常。

但我有一个要求,我需要根据空缺是否已满足来显示过滤数据,即它的活动/待定预订少于空缺限制或已订满。

我目前使用的查询是:

SELECT v.*, j.job_category_name, bu.business_unit_name 
FROM vacancy v 
INNER JOIN job_category j ON j.job_category_id = v.job_category_id 
INNER JOIN business_unit bu ON bu.business_unit_id = v.business_unit_id 
INNER JOIN booking b ON b.vacancy_id = v.vacancy_id 
INNER JOIN booking_status bs ON bs.id = b.booking_status_id 
WHERE 
    v.vacancy_status <> 'revoked' AND 
    v.vacancy_reference <> 'auto-generated booking' AND 
    v.business_unit_id IN (series of primary keys) AND 
(bs.booking_status_type_id = 1 OR bs.booking_status_type_id = 2) 
GROUP BY v.vacancy_id 
HAVING v.vacancy_limit > count(b.booking_id)
ORDER BY v.vacancy_id DESC

当我撤销预订时出现问题(booking_status_type_id 4)。它似乎弄乱了结果或没有得到任何结果。

预订状态更改的小场景可能是:-

  1. 用户创建预订(待定状态)
  2. 客户端接受(活动状态)
  3. 然后客户端决定撤销(Revoke state)

这将导致如下条目:-

Vacancy ID = 100;
Booking ID = 10;
Booking Status entries:-

Booking_id    Booking_status_type_id
---------------------------------------
10            1
10            2
10            4

因此,理论上该预订不应显示在结果中,因为该职位已被删除并再次可用。

这将在 booking_status_type 表中产生 3 个条目,用于预订状态更改。

我不确定为什么我的查询不起作用,或者它的构造是否正确。作为一项基本要求,当用户选择是否未完成预订时,它应该只显示预订总和不超过预订限制的空缺。

同样,在选择填充空位时选择过滤时,它应该仅在达到限制的情况下显示空缺。

编辑#1

好的,我已尝试实施建议的解决方案,但无法正常工作:

SELECT v.*, j.job_category_name, bu.business_unit_name  
FROM vacancy v  
INNER JOIN job_category j ON j.job_category_id = v.job_category_id  
INNER JOIN business_unit bu ON bu.business_unit_id = v.business_unit_id  
INNER JOIN booking b ON b.vacancy_id = v.vacancy_id  
INNER JOIN  
(SELECT booking_id AS bk_id, max(booking_status_type_id) AS bStatus
FROM booking_status
GROUP BY bk_id
HAVING bStatus < 3) as filter ON filter.bk_id = b.booking_id 
WHERE  
    v.status <> 'revoked' AND  
    v.reference <> 'auto-generated booking' AND  
    v.business_unit_id IN (1, 2) 
GROUP BY v.vacancy_id  
HAVING v.limit > count(b.booking_id) 
ORDER BY v.vacancy_id DESC

我收到以下错误:

1064 - 您的 SQL 语法有错误。检查手册,

对应于你的 MySQL 服务器 使用正确语法的版本 'SELECT booking_id AS bk_id 附近, 最大值(booking_status_type_id)AS b

MySQL的版本是4.0

【问题讨论】:

  • 查询看起来不错,但如果没有数据,就很难判断出了什么问题。尝试简化问题。例如,从联接中删除那些您实际上不需要的表(business_unit、job_category)。我的猜测是之后你可以自己解决问题。

标签: sql count inner-join having-clause


【解决方案1】:

您正在计算状态为 1 或 2 的预订,但我认为您应该计算状态不为 3 或 4 的预订 - 即消除被拒绝或撤销的预订。罢工>

实际上,我现在看到您仅使用预订表中的联接选择了一种预订状态。我怀疑当时的数据。您确定booking_status_id中的id所指的预订状态是最新的吗?

对此进行了探索,我会检查以下内容:

  1. 是否存在多个具有相同 ID 的预订状态?
  2. 链接的预订状态是最新的吗?
  3. 您确定您是通过 status id 而不是 booking id 加入的吗?

除此之外,我看不到。

【讨论】:

  • 真的!!!我认为加入是在 booking_id 之间,但这不是问题,booking_id 上必须有一个缺少的加入条件
  • 是的,bookings 表上的 booking_status_id 是最新的状态变化。
  • 我不确定 booking_id 是否需要加入条件。预订和预订状态之间的联系我们在预订中预订状态id的外键之间。尽管出于审计和报告目的,我确实将 booking_id 存储在 booking_status 表中。
  • 我设法重写了我的查询,以便它计算左连接上的预订。问题是由于(我认为)我的查询包含预订状态更改的所有计数的速度很快。
【解决方案2】:

问题是您忽略了预订状态可能有多个相同预订 ID 的事实,因此您需要首先过滤有效的预订 ID,如下所示

select booking_id as bk_id, max(Booking_status_type_id) status
from booking_status
group by booking_id
having status < 3

此查询将仅返回待处理或活动的预订 ID,然后您可以根据此进一步应用您在提到的查询中应用的所有联接来过滤空缺。 我已经粗略地修改了你的查询来做到这一点,检查它是否有效

SELECT v.*, j.job_category_name, bu.business_unit_name 
FROM vacancy v 
INNER JOIN job_category j ON j.job_category_id = v.job_category_id 
INNER JOIN business_unit bu ON bu.business_unit_id = v.business_unit_id 
INNER JOIN booking b ON b.vacancy_id = v.vacancy_id 
INNER JOIN 
(select booking_id as bk_id, max(Booking_status_type_id) status
from booking_status
group by booking_id
having status < 3) as filter ON filter.bk_id = b.booking_id
WHERE 
    v.vacancy_status <> 'revoked' AND 
    v.vacancy_reference <> 'auto-generated booking' AND 
    v.business_unit_id IN (series of primary keys)
GROUP BY v.vacancy_id 
HAVING v.vacancy_limit > count(b.booking_id)
ORDER BY v.vacancy_id DESC

【讨论】:

  • 具有 (bs.booking_status_type_id = 1 OR bs.booking_status_type_id = 2) 子句是否满足该条件?
  • 这还不够,因为仅给出条件 (bs.booking_status_type_id = 1 OR bs.booking_status_type_id = 2) 也会匹配可能存在拒绝或撤销行的预订 ID
  • 克叔,我想你可能是对的。昨天我越想,我就越意识到我没有事先过滤状态。我今天要尝试模拟一个数据库并对其进行测试,因为我要到明天才上班。
  • 我想到的另一个选项是我实际上不需要屏幕上的任何预订详细信息,所以我想代替加入预订和预订状态表,只需将计数应用于.例如 where v.limit > (select count(b.booking_id) from booking inner join booking_status bs on bs.id = b.id where bs.booking_status_type_id in (1, 2) and b,vacancy_id = v.vacancy_id)
猜你喜欢
  • 1970-01-01
  • 2014-06-04
  • 2021-07-21
  • 2021-06-15
  • 2012-02-08
  • 1970-01-01
  • 2021-02-23
  • 1970-01-01
  • 2011-10-07
相关资源
最近更新 更多