一天摘要的 VBA 访问查询
Posted
技术标签:
【中文标题】一天摘要的 VBA 访问查询【英文标题】:VBA Access Query for Day Summary 【发布时间】:2015-01-27 22:36:27 【问题描述】:我一直在这个论坛上寻求 VBA 帮助,但这是我第一次自己发帖。
我正在尝试制作一份报告,提供存储在 Access 中的各种警报的摘要。我想每天提供每个警报的简单计数。我使用了一些 SQL 查询,但没有真正使用任何 Access。我认为 Access 可以从 Access 本身执行数据透视表。如果有更好的方法,请告诉我。
Set CommandQuery.activeConnection = conn
commandQuery.CommandText = _
"TRANSFORM Count(FixAlarms.[Alm_NativeTimeLast]) AS CountOfAlm_NativeTimeLast " & _
"SELECT FixAlarms.Alm_Tagname, FixAlarms.Alm_Desc " & _
"FROM FixAlarms " & _
"WHERE ((FixAlarms.Alm_Tagname) <> """")) AND FixAlarms.Alm_NativeTimeIn > CellTime " & _
"GROUP BY FixAlarms.[Alm_Tagname], FixAlarms.Alm_Descr " & _
"PIVOT Format([Alm_NativeTimeIn],""Short Date"")"
rec.Open commandQuery
这是我正在使用的代码。我不得不重新输入它,所以请原谅任何错字。它完成了我想要的大部分工作,但它没有给我任何关于每列是哪一天的指示。我需要在每一列上都有一个标题,以防有一天没有警报。我认为答案在于 PIVOT 的 IN 部分,但如果没有语法错误,我无法让它工作。我以为我所要做的就是添加
PIVOT Format([Alm_NativeTimeIn],""Short Date"") IN 01/20/15"
如果可以的话,请帮忙。
谢谢。
【问题讨论】:
【参考方案1】:为了获得一整天的记录,即使是那些你需要创建这些天没有活动的记录。在访问中执行此操作的最简单方法是使用一组 UNION 语句为类似于此的日期创建一个假表:
SELECT #2015-01-20# as dt FROM dual
UNION ALL
SELECT #2015-01-21# as dt FROM dual
UNION ALL
SELECT #2015-01-22# as dt FROM dual
如果您在 Access 中尝试上述查询,它将不起作用,因为没有名为 dual
的表。您将不得不创建它。检查this SO 问题。
创建上述查询后,您可以将其与源表 LEFT JOIN。
TRANSFORM Count(FixAlarms.[Alm_NativeTimeLast]) AS CountOfAlm_NativeTimeLast
SELECT FixAlarms.Alm_Tagname, FixAlarms.Alm_Desc
FROM
(SELECT #2015-01-20# as dt FROM dual
UNION ALL
SELECT #2015-01-21# as dt FROM dual
UNION ALL
SELECT #2015-01-22# as dt FROM dual) as dates LEFT JOIN
FixAlarms ON DateValue(FixAlarms.[Alm_NativeTimeIn]) = dates.dt
WHERE ((FixAlarms.Alm_Tagname) <> """")) AND FixAlarms.Alm_NativeTimeIn > CellTime
GROUP BY FixAlarms.[Alm_Tagname], FixAlarms.Alm_Descr
PIVOT Format(dates.dt, 'Short Date')
编辑:我必须补充一点,这不是实现它的唯一方法。另一种方法是使用Numbers
表。创建一个名为Numbers
的表,其中包含一个数字列n
,并用数字0 到100 填充它(取决于您希望包含在查询中的最大天数)。那么您对dates
的查询将是:
SELECT DateAdd('d', n, #2015-01-20#) as dt FROM numbers where n
结果查询将是:
TRANSFORM Count(FixAlarms.[Alm_NativeTimeLast]) AS CountOfAlm_NativeTimeLast
SELECT FixAlarms.Alm_Tagname, FixAlarms.Alm_Desc
FROM
(SELECT DateAdd('d', n, #2015-01-20#) as dt FROM numbers where n < 30) as dates LEFT JOIN
FixAlarms ON DateValue(FixAlarms.[Alm_NativeTimeIn]) = dates.dt
WHERE ((FixAlarms.Alm_Tagname) <> """")) AND FixAlarms.Alm_NativeTimeIn > CellTime
GROUP BY FixAlarms.[Alm_Tagname], FixAlarms.Alm_Descr
PIVOT Format(dates.dt, 'Short Date')
【讨论】:
查,谢谢你的回答。我不完全理解为什么当我已经有一个 Date 列可以使用时,我必须创建另一个列。真的,只要每列都有一个标题,我就可以不用空白列。然后我可以编写一个宏来放置它们并对其进行排序。我不明白为什么在 Access 执行查询时查询具有列名,但是当我将其复制到 VBA 时却没有。也许这是我缺少的一些连接设置? 如果您没有某个范围内所有日期的数据,则该数据不会出现在 select 语句中。因此,当您转换此选择语句时,将不会创建列,从而导致间隙。通过使用 LEFT JOIN,您可以确保至少为缺失的日期创建了一行。只需尝试上述查询,看看它们是否产生所需的结果【参考方案2】:当使用PIVOT columnName IN (ValueList)
ValueList
是
-
括号内
带引号
逗号分隔
所以你是
PIVOT Format([Alm_NativeTimeIn],""Short Date"") IN 01/20/15"
需要成为
PIVOT Format([Alm_NativeTimeIn],""Short Date"") IN (""01/20/15"")
话虽如此,这不会在 IN 语句中使用 PIVOTS 过滤您的记录。您仍然需要使用 WHERE 子句。
如果最终目标是从左到右表示您的数据,那么这将起作用。但是,将这项工作作为报告工作将是很多额外的工作,因为您的控件不会绑定到可预测的列。列名会因不同的参数而改变。
您可以将其保留为传统查询(未转置)并更轻松地报告它。如果您是直接向用户显示网格或导出到 Excel,那么这不是问题。
【讨论】:
【参考方案3】:所以,我只想在我的数据透视表中添加一个标题,告诉我特定列的日期。 我没有显示的部分代码是我正在使用 rec.getrows 将我的所有数据移动到一个更简单的数组变量中。虽然这包含来自 Access 的所有数据,但它没有任何标题来告诉我什么是标记名、什么是描述以及什么是哪个日期。
我发现在 fields.item(n) 下的记录集本身中有一个 Name 属性。这个名称告诉我列数据的来源或数据的日期。使用此功能和一个简单的日期(日期)函数,我能够制作汇总所有警报的月度报告。
感谢你们的帮助,但我对问题的描述不是很清楚,就是想多了。
【讨论】:
以上是关于一天摘要的 VBA 访问查询的主要内容,如果未能解决你的问题,请参考以下文章