【问题标题】:How can I get a record to be counted in multiple columns of a Crosstab Query?如何在交叉表查询的多个列中计算一条记录?
【发布时间】:2019-12-12 08:43:12
【问题描述】:

背景资料:

  1. 我的公司要求员工在某个职位上至少持有一项认证 (cert)。员工总共可以获得 17 种不同的认证。

  2. 一名员工可以持有多个证书。但是在任何一天,他们都只能“坐”到他们获得认证的职位之一。大多数员工主要担任他们持有证书的最高级别职位,但如果该职位出现人员短缺,则可以担任较低级别的职位职位以及他们是否持有该特定证书(一些员工来找我们持有较高级别的证书,但没有较低级别的证书,因为他们让它们过期)。

  3. 多个员工可以持有同一个证书。

  4. 大约 90% 的员工签订合同,这意味着他们有固定的终止日期。合同可以延期,但为了这个 Access 数据库和要生成的报告,我们假定终止日期是一成不变的。

我的老板(和老板的老板)想要整理一份人力预测报告,这样他们就不会在我们开始缺乏任何一个职位的认证员工时措手不及。

他们想要的示例:

假设您有 3 名员工:

  • Employee1position1position2position3 拥有证书,但他主要以position3 的身份任职,他的合同将于2020 年6 月到期。

  • Employee2 拥有 position1position2 的证书,但主要以 position2 身份担任,她的合同将于 2022 年 2 月到期。

  • Employee3 是新的,于 2019 年 8 月到达,正在接受 position1 的培训,初始证书的最长允许培训时间为 3 个月,因此他应该在 2019 年 12 月之前获得 position1 证书,并且他的合同将于 2025 年 8 月到期。

假设我的老板想要预测 12 个月,起始月份是 2019 年 11 月(他只能选择等于或晚于当前月份年份的起始月份年份)。下面的图表是在子报表中生成的,应该是根据上述员工信息生成的。

所有认证图表

+-----------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|   Cert    | Nov 19 | Dec 19 | Jan 20 | Feb 20 | Mar 20 | Apr 20 | May 20 | Jun 20 | Jul 20 | Aug 20 | Sep 20 | Oct 20 |
+-----------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| Position1 |      2 |      3 |      3 |      3 |      3 |      3 |      3 |      2 |      2 |      2 |      2 |      2 |
| Position2 |      2 |      2 |      2 |      2 |      2 |      2 |      2 |      1 |      1 |      1 |      1 |      1 |
| Position3 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      0 |      0 |      0 |      0 |      0 |
+-----------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+

主要认证图表

+-----------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|   Cert    | Nov 19 | Dec 19 | Jan 20 | Feb 20 | Mar 20 | Apr 20 | May 20 | Jun 20 | Jul 20 | Aug 20 | Sep 20 | Oct 20 |
+-----------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| Position1 |      0 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |
| Position2 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |
| Position3 |      1 |      1 |      1 |      1 |      1 |      1 |      1 |      0 |      0 |      0 |      0 |      0 |
+-----------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+

现在我已经有了一个解决方案,但它极其效率低下,并且涉及对每个单元格的查询(2 个图表 X 12 个月 X 17 个职位 = 生成报告时的 408 个查询)。我希望通过交叉表查询做一些更有效的事情。

表格是这样设置的(仅列出相关字段):

Emp_table

  • ID(自动编号)
  • contractStarted(日期)
  • contractEnd(日期)

Cert_individual

  • ID(自动编号)
  • certID (num, many->一个关系到cert_table.ID)
  • EmpID (num, many->一个关系到Emp_table.ID)
  • date_cert_received(日期)
  • primary(是/否)

cert_table

  • ID(自动编号)
  • cert_name(短文)

显然我需要做几个INNER JOINS 才能将所有内容放在一起,我尝试使用this website 中的格式进行交叉表查询,但它只会在当月的计数中添加一个单独的证书- 员工收到证书的年份,而不是员工持有证书的每个月。

所以我的问题是:

SQL 或 VBA 中是否有一种方法可以根据员工收到证书的时间以及合同计划终止的时间来跨多个列(月-年)计算证书?

【问题讨论】:

  • 答案是:大多数事情都可以用足够多的代码和不止一种方法来完成。您已经有了一种仅使用 SQL 的方法,但是结合使用 SQL 和 VBA 以及临时表可能会更有效。以某种方式生成所有可能的月-年/员工对的数据集当然是可能的,但我只是怀疑。
  • 更正,需要所有可能的月-年/员工/证书组合的数据集来作为 CROSSTAB 的基础。编辑问题以显示源数据表的示例。
  • How to ask a good SQL question。示例数据和预期结果比文字描述更有用。

标签: sql ms-access crosstab ms-access-2016


【解决方案1】:

据我所知,获取交叉表查询的主要问题是它只能生成包含您已有数据的列。

获取月度列的解决方案是使用包含 12 个日期的边表,然后使用笛卡尔积为您的认证表中的每条记录生成月度数据。可以更新和维护此“日期”表,以匹配您在报告中需要查询的月份。


例如,如果您有一个名为 TempDates 的表:

还有一个带有Employees 的表格,其中包含以下数据:

您可以使用我命名为QryCertsDates 的查询生成笛卡尔积:

SELECT Employees.*, TempDates.* FROM TempDates, Employees;

这使您可以将所有想要的日期与表Employees 中的原始日期附加在一起,以获得类似于以下的数据:

现在您可以生成以月和年为轴心的交叉表查询,并使用 WHERE 条件过滤日期,例如:

TRANSFORM Count(QryCertsDates.Cert) AS CountOfCert SELECT QryCertsDates.Cert FROM QryCertsDates WHERE (((CDate([Yr] & "-" & [Mo])) Between CDate([Start]) And CDate([Expire]))) GROUP BY QryCertsDates.Cert PIVOT CDate([Yr] & "-" & Format([Mo],"00"));

你最终会得到这样的结果:

您也可以执行相同的操作来获取第二个表格/报告。我不知道您的数据库结构,因此您很可能需要进行一些调整。获得类似结果的另一种可能方法是使用 VBA 填写表格。

但是,这可能是更容易实施的解决方案。祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    • 2016-02-22
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 2013-12-13
    • 1970-01-01
    相关资源
    最近更新 更多