views:

82

answers:

5

I have a query in SQL Server that I am trying to convert to a query in MS-Access 2003. The query is designed to be used as the basis for a report. The report has two fields .. 'Cases Assigned' and 'Cases Closed'.

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'

I am having difficulty using the SQL in Access 2003. I have replaced the ' characters with # for Access's sake but still no joy. Does Access have a problem with SELECT within SELECT statements? The error I get from Access is less than helpful.

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

Also, what if the SQL statement was such that data needed to be obtained from more than one table. For example ...

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'

This works in SQL without issue, but not in Access.

A: 

3205 error is Too many crosstab column headers .

Does this query solution for you:

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')

result will in two rows instead of one.

Michael Pakhantsov
Since this will be the basis for a report, is there a way to return the results as 1 row with multiple columns?
webworm
+1  A: 

I haven't a Windows machine to test on at the moment, but something like this should work.

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 

In my experience it is generally preferable, where possible, to avoid using subqueries in Access.


Edit:
Responding to your comment, I just tested that Access allows this alternative method:

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 will work if you need a one-row resultset.

Adam Bernier
This works if all the data is coming from one table. How could it be modified if other tables need to be queried?
webworm
@webworm: please see my edit. I am not so sure that splitting up those data is the best table structure. However, that's another question entirely. Best of luck to you.
Adam Bernier
@Adam Bernier - First thank for your assitance. It is much appreciated! The situation I have is I need to create a single report where data is gleaned from several non related tables. I am trying to get a single row result set so I can bind the report to the results. My problem is that data is all in SQL Server but my front-end is in access. I am trying my best to end up with a single row where each field will contain a total/count for my report.
webworm
@webworm: littlegreen's answer is ideal, then.
Adam Bernier
A: 

Nested queries are allowed in Access as well as in SQL server, but at least in SQL server it requires that you set a dummy alias for your nested query, and all columns in your nested query need a name. This might have caused the error.

I would suggest following query:

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
littlegreen
I ran this within Access and it worked! This was ideal for me because I needed to aggregate data from fields that were in separate and un-related tables. This allowed be to collect all aggregates data as a single row result set allowing me to use it as the basis for a report. Thanks @littlegreen!
webworm
"SQL server it requires that you set a dummy alias for your nested query, and all columns in your nested query need a name" -- I think you misread the query: these are scalar subqueries in the `SELECT` clause and there is no requirement for column 'aliases' nor table correlation names. You seem to be talking about derived tables in a `FROM` clause.
onedaywhen
In that case 'as q1' and 'as q2' may be omitted. I cannot test it at the moment but you may well be right.
littlegreen
+1  A: 

I don't know where you're getting this error message, but your problem is trying to execute a Select statement without at least a table or query. You'll need some sort of 'dummy' table with just one record to accomplish this.

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;
Jeff O
Could you explain why this "DummyTableWithOneRecord" is needed? Seems like a bit of a hack. Does the record have to contain a certain number of fields? Specific names?
webworm
I should explain what I meant by hack. Not hack in a bad way but more that I really didn't understand how it was working. I tried your suggestion but I got a NULL result set back. No rows and no field.
webworm
+ for actually answering the question i.e. Select statement requires a table.
onedaywhen
@webworm: "why this "DummyTableWithOneRecord" is needed? Seems like a bit of a hack." -- In Standard SQL, a `SELECT` requires a table. For a change, Access has got it right :) It is SQL Server that provides the "hack" by allowing you to use `SELECT` in absence of a table e.g. `SELECT 1;` is valid on SQL Server and actually returns a resultset too, but violates the Standard ...or extends it, if you prefer :) To do it properly (or on Access) you would need `SELECT 1 FROM AnyTable;` assuming AnyTable has exactly one row or `SELECT DISTINCT 1 FROM AnyTable;` assuming AnyTable has at least one row.
onedaywhen
@onedaywhen - Select 1 as TheOne; will work in 2007.
Jeff O
@Jeff O: "`Select 1 as TheOne;` will work in [ACE] 2007" -- indeed and is equivalent to my `SELECT 1 FROM AnyTable;`, assuming that `TheOne` has but one row.
onedaywhen
@onedaywhen - no TheOne is a column alias and not a table.
Jeff O
`Select 1 as TheOne` works in A2003, too.
David-W-Fenton
+1  A: 

Since you have a query which works in SQL Server, create an Access pass-through query which uses that query (in SQL Server) and returns the result set to Access.

Alternatively, create a SQL Server view based on that SELECT statement and link to the view from Access.

Since it already works in SQL Server, I don't see any added value from re-creating the query in Access.

HansUp
+1 if you can't beat them, join them.
Adam Bernier
INNER JOIN? :-)
HansUp
Well, in Access it certainly can't be an OUTER JOIN!
David-W-Fenton