tags:

views:

65

answers:

2

Okay this one has me stumped.. mainly because i have been working on this problem for the entire day and I (and boss) decided to go an alternative route. However my brain is fried.

I present to you the following picture:

alt text

Now the left hand table is the export table (it is not a physical table). This is what I want. The 5 right hand tables are where the data is coming from.

I want the data from the latest month + 11 previous months. (in some situations like the example shown, there is data only for the one month. So for the previous 11 months I *DO * want the 12 months to show with 0 as the count entries. Is that possible? Please look at my hand drawn picture at the end)

Note: Please note that the left hand side table is not an physical table. it is the result of a SQL SELECT statement

The current SQL statement looks like this. It grabs EVERYTHING (not 12 months) and it does a weird join which fails in my current example:

SELECT A.month, A.count, B.count, C.count, D.count, E.count
FROM [table name] AS A, [table name]  AS B, [table name]  AS C, [table name]  AS D, [table name] AS E
WHERE B.month=A.month and C.month=A.month and D.month=A.month and E.month=A.month
ORDER BY A.month DESC;

I am gonig to draw a picture of what I want the final to look like

+=============================================================+
|  month    | A.count | B.count | C.count | D.count | E.count |
+-------------------------------------------------------------+
|2010-08-01      3           2       0          5        18   |
|2010-07-01      0           0       0          0         0   |
|2010-06-01      0           0       0          0         0   |
|2010-05-01      0           0       0          0         0   |
|2010-04-01      0           0       0          0         0   |
|2010-03-01      0           0       0          0         0   |
|2010-02-01      0           0       0          0         0   |
|2010-01-01      0           0       0          0         0   |
|2010-12-01      0           0       0          0         0   |
|2010-11-01      0           0       0          0         0   |
|2010-10-01      0           0       0          0         0   |

etc
A: 

You can accomplish this by including sub-queries in your SELECT.

    SELECT MonthDate,
    (
      SELECT COUNT(*) FROM A WHERE A.Month = M.MonthDate
    ) [A.Count],
    (
      SELECT COUNT(*) FROM B WHERE B.Month = M.MonthDate
    ) [B.Count],
    (
      SELECT COUNT(*) FROM C WHERE C.Month = M.MonthDate
    ) [C.Count],
...
    FROM Months M

For more info on sub-queries see: http://allenbrowne.com/subquery-01.html

Leon
+1  A: 

I have used a number table for this called Counter with a field Num containing sequential integers up to at least 12.

SELECT x.Mnth, Nz([a].[Count],0) AS a, 
       Nz([b].[Count],0) AS b, Nz([c].[Count],0) AS c, 
       Nz([d].[Count],0) AS d, Nz([e].[Count],0) AS e
FROM (((((SELECT DateAdd("m",-[Num],#2010/7/1#) AS Mnth 
          FROM [Counter] WHERE Num<=12)  AS x 
LEFT JOIN a ON x.Mnth = a.month) 
LEFT JOIN b ON x.Mnth = b.month) 
LEFT JOIN c ON x.Mnth = c.month) 
LEFT JOIN e ON x.Mnth = e.month) 
LEFT JOIN d ON x.Mnth = d.month
ORDER BY a.Count DESC;
Remou
This produces an error. Can you have "Select .. AS A" in the select part? or is that only for the FROM part?
masfenix
I tested in Access and it worked for me. Do you have the counter table set up?
Remou
The syntax for derived tables will depend on your SQL mode. If SQL 92, the above should work, but if SQL 89 (the legacy default), you need FROM [SELECT...]. As Alias.
David-W-Fenton
Eh? I am using the legacy default. There is absolutely nothing wrong with `Nz([a].[Count],0) AS a`, which is what I think masfenix is asking about, it has worked in Access for yonks. I even tested with Access 2000.
Remou
It is not exactly a derived table, it relies on a counter or number table containing integers to get the dates, so not so different to formatting. Such tables are enormously useful for any, he he, number of things, as I am sure you know.
Remou
Completely missed the counter table part. Like I said .. brain fried. I'll try it again on monday.
masfenix
I know the feeling only too well :)
Remou
You have a a "derived table" in your FROM clause, specifically, the first "table" in your FROM clause is a derived table, i.e., "(SELECT...) As x". You're using a derived table to filter your counter table. The syntax with curved braces won't work without SQL 92 mode turned on (and that, only in A2003 and later). For it to work in SQL 89 mode, it has to be: "[SELECT...]. As x".
David-W-Fenton
Did you miss the bit where I said I had tested in Access 2000? I have been using Select () with Access for quite a while. You will get problems with Select []. in the query design window when you make changes to the query in design view. This came up in Tek-Tips quite recently.
Remou
Hey this is still giving me an error. The error is at the "a" after `Left Join` statement. It says `it can not find input table or query 'a'`
masfenix
This is going to be run on A2003
masfenix
Third comment: If i change the syntax for `AS ast` instead of `AS a` and change the `LEFT Join a` to `LEFT Join ast` it gives me a syntax error in join statement.
masfenix
LOL I am an idiot. I forgot I had to change the 'a's and bs to the actual table names. So now I get a new error "Type mismatch". The `month` field in the actual tables is a `text` field im afraid.
masfenix
What are your tables called? Your picture shows a,b,c,d,e so each of : LEFT JOIN a ON x.Mnth = a.month) : need to be changed to the table name : LEFT JOIN ast ON x.Mnth = ast.[month]) : you may need to change month to the name of the dat field. Next, you need to change each of these : [a].[Count] to the table name, if it is ast for a, this would read : [ast].[Count] . As is not important, you can have [ast].[Count] As a : or [a].[Count] As ASTCount : whatever suits.
Remou
Hey, I think we just commented at the same time. yea, dumb me. I figured that out. Now i need to somehow convert the x.Month to text
masfenix
Why would you need to do that?
Remou
because the month field on the tables (a, b,c, d, e) is a string, and the Mnth on the counter table is being grabbed as a date. Its okay, i just put that around `str()` and it worked, otherwise it would be give me a mismatch error. HOWEVER, i am getting 0 data :( .. i get my grid, but all of them are zeros
masfenix
If anything, you should be converting ast.Month to date CDate(ast.[Month])
Remou
You might like to post the sql as amended to suit your system.
Remou
I think the problem is that my month field on my tables a, b, c.. are in the format `year-month-date`. The month being derived from the counter table which is also being joined is in the format `year\month\date` .. which in terms of strings don't match and its giving 0 data.
masfenix
Use CDATE on the a,b,c ... tables, leave the date alone on x
Remou
PERFECT! .. however, Is it possible to supply the month? like lets say I am running the report for august, i want it to date back to last august. Its always last 12 months from a date which i supply. I have the date in a variable in the VBA.
masfenix
Yes, you can say `WHERE a.month <=#2010/7/1# OR a.month Is NullAND b.month <=#2010/7/1# OR b.month Is Null` and so on. You can also refer to a form control : `WHERE a.month <=Forms!PickDate!StartDate`
Remou
sorry, but I would need to update the counter table for that right?
masfenix
Hm, gimme a minute :)
Remou
I was thinking of just updating the counter table with the last 12 months from VBA. Then from the SQL you gave me, instead of creating a date using `dateserial()` and manually building the date, I just pull it out of Counter
masfenix
I just tried this and this works!
masfenix
Okay this is much better: SELECT DateAdd("m",-[Num],#2010/7/1#) AS Mnth FROM [Counter] WHERE Num<=12 I will edit my answer
Remou
but I can't hardcode the 2010/7/1 .. the report is run on the first of every month. So it will run September 1st, for the months August 2009 - August 2010.
masfenix
The thing about a counter table is that it is not an uncommon inclusion in a database, because it can be used for a number of reasons.
Remou
You don't have to, you can use a parameter or refer to a form.
Remou
You can even use the current date: SELECT DateAdd("m",-[Num],Date())
Remou
Oh okay. How would I make it refer to a variable (or a function that returns the variable) ?Can I include the `Forms!` command? the thing is the variable is a global variable defined in a module.
masfenix
You can refer to a control on a form (eg Forms!PickDate!StartDate), which can be set to the variable, but if you wish to refer to a global variable in the SQL, you need either use a parameter or to build the SQL in VBA.
Remou
okay, because I am cleaning up someone else's code, I'd rather not deal with VBA. There's already a ton of spaghetti code in here. Would my way cause problems in the future? I populate the counter table for the last 12 months using VBA and use that instead of `Num` and creating my own date.
masfenix
It will cause more problems than simply changing the sql through VBA, because it will increase the size of the database, but perhaps not by that much. Why not use a form which offers the best solution and almost no coding?
Remou
@Remou: I cannot get curved braces to work in A2000 at all, nor in A2003 without SQL 92 mode turned on. The square bracket syntax is problematic because you often need them inside the SQL SELECT for your derived table (though not if you name your fields in ways that never require brackets), so I'd be thrilled if I could use round braces on a regular basis without changing SQL mode, but I have not found that to be possible at all, and absent SQL 92 mode being on, it does not work on any version of Access I've tested (A97, A2000, A2003, A2007, A2010).
David-W-Fenton
I have just re-tested with Access 2000 on a laptop running Vista that has never had a more recent version of Access installed: SELECT a.Fld FROM (SELECT * FROM tbl) AS a. I cannot swear to it, but I think I have been posting solutions for a good few years with (SELECT ..)
Remou
On my A2003 and 2007 systems, the parentheses style for derived queries works fine in SQL-89 mode. One thing I notice is even small changes made in the query designer generally cause Access to change my parentheses to the square-brackets-plus-dot style. I don't know if that has any bearing on the differences we're seeing.
HansUp
Yep. I get that, too. And it can seriously mess up a query if it is not changed back.
Remou
I type the stuff in manually in SQL view with () and it won't work, ever.
David-W-Fenton
Well, bloody hell, I just tried it again, and it works. I haven't a clue what I was doing differently to make it not work. One difference between today and the last time I tested is that I installed SQL Server Express 2008 R2 and all the huge pile of bloody dependencies. Maybe something in that jogged something loose, but I also couldn't get it to work on my Win7 laptop with 2003 and 2010 installed.
David-W-Fenton