将 SQL 查询转换为访问查询 - SELECT 中的 SELECT

Posted

技术标签:

【中文标题】将 SQL 查询转换为访问查询 - SELECT 中的 SELECT【英文标题】:Converting SQL Query to Access Query - SELECT within SELECT 【发布时间】:2010-09-30 15:10:03 【问题描述】:

我在 SQL Server 中有一个查询,我试图将它转换为 MS-Access 2003 中的一个查询。该查询旨在用作报告的基础。该报告有两个字段..“已分配案例”和“已关闭案例”。

SELECT 
(SELECT COUNT(*) 
FROM CaseDetail 
WHERE CaseAssignedDate Between '1/1/2008' AND '1/1/2009') as 'Cases Assigned',
(SELECT COUNT(*) 
FROM CaseDetail 
WHERE CaseClosedDate BETWEEN '1/1/2008' AND '1/1/2009') as 'Cases Closed'

我在 Access 2003 中使用 SQL 时遇到困难。为了 Access 的缘故,我已将 ' 字符替换为 #,但仍然没有乐趣。 Access 在 SELECT 语句中是否存在 SELECT 问题?我从 Access 得到的错误没有什么帮助。

Reserved error (-3205); there is no message for this error

另外,如果 SQL 语句需要从多个表中获取数据怎么办。比如……

SELECT 
(SELECT COUNT(*) 
FROM AssignedCases
WHERE CaseAssignedDate Between '1/1/2008' AND '1/1/2009') as 'Cases Assigned',
(SELECT COUNT(*) 
FROM ClosedCases
WHERE CaseClosedDate BETWEEN '1/1/2008' AND '1/1/2009') as 'Cases Closed'

这在 SQL 中有效,但在 Access 中无效。

【问题讨论】:

【参考方案1】:

我不知道您从哪里收到此错误消息,但您的问题是尝试在没有表或查询的情况下执行 Select 语句。您需要某种只有一条记录的“虚拟”表来完成此操作。

SELECT  
    (SELECT COUNT(*)  
     FROM CaseDetail  
     WHERE CaseAssignedDate Between '1/1/2008' AND '1/1/2009'
    ) as 'Cases Assigned', 
    (SELECT COUNT(*)  
     FROM CaseDetail  
     WHERE CaseClosedDate BETWEEN '1/1/2008' AND '1/1/2009'
    ) as 'Cases Closed' 
FROM DummyTableWithOneRecord;

【讨论】:

你能解释一下为什么需要这个“DummyTableWithOneRecord”吗?似乎有点骇人听闻。记录是否必须包含一定数量的字段?具体名称? 我应该解释一下我所说的 hack 是什么意思。不是以一种糟糕的方式破解,但更多的是我真的不明白它是如何工作的。我尝试了你的建议,但我得到了一个 NULL 结果集。没有行也没有字段。 + 用于实际回答问题,即 Select 语句需要一个表格。 @webworm:“为什么需要这个“DummyTableWithOneRecord”?看起来有点小技巧。” -- 在标准 SQL 中,SELECT 需要一个表。对于更改,Access 做对了 :) SQL Server 通过允许您在没有表的情况下使用SELECT 来提供“hack”,例如SELECT 1; 在 SQL Server 上有效,并且实际上也返回了一个结果集,但违反了标准 ...或扩展它,如果您愿意的话:) 要正确地(或在 Access 上)执行此操作,您需要 SELECT 1 FROM AnyTable; 假设 AnyTable 完全一行或SELECT DISTINCT 1 FROM AnyTable; 假设 AnyTable 至少有一行。 @Jeff O: "Select 1 as TheOne; will work in [ACE] 2007" -- 确实相当于我的SELECT 1 FROM AnyTable;,假设TheOne 只有一行。【参考方案2】:

我目前还没有要测试的 Windows 机器,但这样的东西应该可以工作。

SELECT SUM(IIF(CaseAssignedDate 
           BETWEEN #1/1/2008# AND #1/1/2009#, 1, 0)) AS CasesAssigned,
       SUM(IIF(CaseClosedDate 
           BETWEEN #1/1/2008# AND #1/1/2009#, 1, 0)) AS CasesClosed
  FROM CaseDetail 

根据我的经验,通常最好尽可能避免在 Access 中使用子查询。


编辑: 回应您的评论,我刚刚测试了 Access 是否允许这种替代方法:

SELECT *
  FROM
(
SELECT 'CasesAssigned', COUNT(*) AS Total
  FROM AssignedCases
 WHERE CaseAssignedDate BETWEEN #1/1/2008# AND #1/1/2009#

UNION ALL

SELECT 'ClosedCases', COUNT(*) AS Total
  FROM ClosedCases
 WHERE CaseClosedDate BETWEEN #1/1/2008# AND #1/1/2009#
);

Edit2:littlegreen's answer 可以在您需要单行结果集时使用。

【讨论】:

如果所有数据都来自一个表,则此方法有效。如果需要查询其他表怎么修改? @webworm:请看我的编辑。我不太确定拆分这些数据是最好的表结构。然而,这完全是另一个问题。祝你好运。 @webworm:那么,littlegreen 的答案很理想。【参考方案3】:

由于您有一个可在 SQL Server 中运行的查询,因此请创建一个 Access 传递查询,该查询使用该查询(在 SQL Server 中)并将结果集返回给 Access。

或者,基于该 SELECT 语句创建一个 SQL Server 视图并从 Access 链接到该视图。

由于它已经在 SQL Server 中运行,我看不到在 Access 中重新创建查询有任何附加价值。

【讨论】:

嗯,在 Access 中它肯定不能是 OUTER JOIN!【参考方案4】:

Access 和 SQL Server 都允许嵌套查询,但至少在 SQL Server 中,它要求您为嵌套查询设置一个虚拟别名,并且嵌套查询中的所有列都需要一个名称。这可能导致了错误。

我建议以下查询:

SELECT q1.CasesAssigned, q2.CasesClosed
FROM 
(SELECT COUNT(*) AS CasesAssigned
FROM CaseDetail 
WHERE CaseAssignedDate Between '1/1/2008' AND '1/1/2009') as q1,
(SELECT COUNT(*) AS CasesClosed
FROM CaseDetail 
WHERE CaseClosedDate BETWEEN '1/1/2008' AND '1/1/2009') as q2

【讨论】:

我在 Access 中运行了它,它成功了!这对我来说是理想的,因为我需要聚合来自单独和不相关表中的字段的数据。这允许将所有聚合数据收集为单行结果集,允许我将其用作报告的基础。谢谢@littlegreen! “SQL 服务器要求您为嵌套查询设置一个虚拟别名,并且嵌套查询中的所有列都需要一个名称”——我认为您误读了该查询:这些是SELECT 子句并且不需要列“别名”或表相关名称。您似乎在谈论 FROM 子句中的派生表。 在这种情况下,'as q1' 和 'as q2' 可以省略。我目前无法对其进行测试,但您可能是对的。【参考方案5】:

3205 错误是交叉表列标题太多。

这个查询解决方案适合你吗:

SELECT 'Cases Asssigned' as Type, COUNT(*) 
FROM CaseDetail 
WHERE CaseAssignedDate Between '1/1/2008' AND '1/1/2009'
UNION
SELECT 'Cases Closed'as Type, COUNT(*) 
FROM CaseDetail 
WHERE CaseClosedDate BETWEEN '1/1/2008' AND '1/1/2009')

结果将在两行而不是一行。

【讨论】:

既然这将是报告的基础,有没有办法将结果作为 1 行多列返回?

以上是关于将 SQL 查询转换为访问查询 - SELECT 中的 SELECT的主要内容,如果未能解决你的问题,请参考以下文章

将具有许多连接的复杂 SQL 查询转换为 Eloquent

将访问查询转换为 sql 2012

如何将命名查询转换为 sql 查询?

将嵌套查询转换为 sql 视图

如何将选择 sql 查询的结果转换为 ms 访问中的新表

将sql连接查询转换为mongodb