| |
|
If this is your first visit, be sure to check out the FAQ by clicking the link above.
You may have to register before you can post: click the register link above to proceed.
To start viewing messages, select the forum that you want to visit from the selection below.
|
 |

10-12-08, 23:53
|
|
Registered User
|
|
Join Date: Oct 2008
Posts: 19
|
|
|
Weird Behaviour - Can someone explain?!
|
|
Hi,
I have a stored proc which simplified looks like:
CREATE PROCEDURE MYPROC(MYVAR VARCHAR10))
....
BEGIN
DECLARE C1 CURSOR FOR
SELECT WO_DATE,
(CASE WHEN LCASE(MYVAR)='a' THEN TABLE.COL1
WHEN LCASE(MYVAR)='b' THEN TABLE.COL2 END) AS FIELD1
FROM TABLE
GROUP BY
WO_DATE,
CASE WHEN LCASE(MYVAR)='a' THEN TABLE.COL1
WHEN LCASE(MYVAR)='b' THEN TABLE.COL2 END
OPEN C1;
END @
When i compiled this I would get the error: SQL0119N: An expression starting with TABLE.COL1 specified in a SELECT, HAVING, ORDER BY is not specified in the GROUP BY....
However, the same CASE statement is in the SELECT and the GROUP BY as shown above so the error baffled me.
It took my hours of playing around but I finally managed to get it working. This is the weird bit, if I simply removed the 'LCASE' function it would work!
Can someone explain this to me as it makes no sense!
ie, the stored proc works fine but now looks like:
SELECT WO_DATE,
(CASE WHEN MYVAR='a' THEN TABLE.COL1
WHEN MYVAR='b' THEN TABLE.COL2 END) AS FIELD1
FROM TABLE
GROUP BY
WO_DATE,
CASE WHEN MYVAR='a' THEN TABLE.COL1
WHEN MYVAR='b' THEN TABLE.COL2 END
|
|

10-13-08, 01:46
|
|
Registered User
|
|
Join Date: Sep 2004
Location: Belgium
Posts: 1,079
|
|
Quote:
|
Originally Posted by chesl73
DECLARE C1 CURSOR FOR
SELECT WO_DATE,
(CASE WHEN LCASE(MYVAR)='a' THEN TABLE.COL1
WHEN LCASE(MYVAR)='b' THEN TABLE.COL2 END) AS FIELD1
FROM TABLE
GROUP BY
WO_DATE,
CASE WHEN LCASE(MYVAR)='a' THEN TABLE.COL1
WHEN LCASE(MYVAR)='b' THEN TABLE.COL2 END
|
I'm assuming you also have an aggregate function (COUNT(*) or so) in the SELECT, otherwise you could just use SELECT DISTINCT of course.
What about one of these two ways of writing the query?
Has to additional advantage of avoiding "code duplication", hence has better maintainability:
Code:
SELECT wo_date, field1
FROM (SELECT wo_date,
CASE WHEN LOWER(myvar)='a' THEN col1
WHEN LOWER(myvar)='b' THEN col2 END AS field1
FROM table) t
GROUP BY wo_date, field1
or the "modern" way:
Code:
WITH t(wo_date, field1) AS
(SELECT wo_date,
CASE WHEN LOWER(myvar)='a' THEN col1
WHEN LOWER(myvar)='b' THEN col2 END
FROM table)
SELECT wo_date, field1 FROM t
GROUP BY wo_date, field1
__________________
--_Peter Vanroose,
__IBM Certified Database Administrator, DB2 9 for z/OS
__IBM Certified Application Developer
__ABIS Training and Consulting
__http://www.abis.be/
|
|

10-13-08, 01:46
|
|
Registered User
|
|
Join Date: Apr 2006
Location: Belgium
Posts: 1,159
|
|
|
|
if you specify select col1,col2.. group by col1
this is not possible if col2 is not an aggregate like sum or other function
it has to be repeated in the group by
__________________
Best Regards, Guy Przytula
Database Software Consultant
DB2 UDB LUW Certified V7-V8-V9-V9.7 DB Admin - Dprop..
Information Server Datastage Certified
http://www.infocura.be
|
|

10-13-08, 01:53
|
|
Registered User
|
|
Join Date: Sep 2004
Location: Belgium
Posts: 1,079
|
|
That's not his problem, I believe.
It's rather the following:
Code:
SELECT complex_function(col1)
FROM table
GROUP BY complex_function(col1)
Apparently, DB2 does not "see" that both complex functions are identical (even if they are literally!) so this must be rewritten the "old" (v7) way, with a nested table expression, before the time "group by expression" was supported, or better of course: use a common table expression (CTE).
__________________
--_Peter Vanroose,
__IBM Certified Database Administrator, DB2 9 for z/OS
__IBM Certified Application Developer
__ABIS Training and Consulting
__http://www.abis.be/
|
|

10-13-08, 05:16
|
|
Registered User
|
|
Join Date: Oct 2008
Posts: 19
|
|
Thanks Peter. The last reply explains the reason which is nice to know.
I'm new to DB2 so I found my answer to remove the lcase function odd.
|
|

10-13-08, 19:36
|
|
Registered User
|
|
Join Date: Oct 2008
Posts: 19
|
|
I've had a look at your alternate query suggestions and I have a question. There's something I can't figure out, excuse my sql skills!
The original query does have a count(id) in it. So, if I wanted to translate the original query to the first example with the nested table, I can't see how it would work as follows:
SELECT t.wo_date, t.field1, count(id) as volume
FROM (SELECT wo_date,
CASE WHEN LOWER(myvar)='a' THEN col1
WHEN LOWER(myvar)='b' THEN col2 END AS field1
FROM table) t, table t2
WHERE t.wo_date = t2.wo_date AND t.field1 = ?????
GROUP BY t.wo_date, t.field1
If I add the count, I'll need to join the two tables together but how can I when the field1 only exists in the nested table? If I don't do the WHERE clause then I get duplicates.
How would I do this?
|
|

10-14-08, 02:02
|
|
Registered User
|
|
Join Date: Sep 2004
Location: Belgium
Posts: 1,079
|
|
Quote:
|
Originally Posted by chesl73
The original query does have a count(id) in it.
If I add the count, I'll need to join the two tables together but how can I when the field1 only exists in the nested table?
|
I don't fully see what you want to do.
Just do as if the nested expression t is a view. Add columns to that view if necessary.
If you want to join table t with table t2 on wo_date *and* on a similar col1/col2 construct, do a similar thing for t2:
Code:
SELECT t.wo_date, t.field1, count(*) as volume
FROM (SELECT wo_date,
CASE WHEN LOWER(myvar)='a' THEN col1
WHEN LOWER(myvar)='b' THEN col2 END AS field1
FROM table1) t,
(SELECT wo_date,
CASE WHEN LOWER(myvar)='a' THEN col1
WHEN LOWER(myvar)='b' THEN col2 END AS field1
FROM table2) t2
WHERE t.wo_date = t2.wo_date AND t.field1 = t2.field1
GROUP BY t.wo_date, t.field1
__________________
--_Peter Vanroose,
__IBM Certified Database Administrator, DB2 9 for z/OS
__IBM Certified Application Developer
__ABIS Training and Consulting
__http://www.abis.be/
|
|

10-14-08, 02:28
|
|
Registered User
|
|
Join Date: Oct 2008
Posts: 19
|
|
Hi,
Sorry Peter, maybe it isn't clear from my last post.
From my original post, I had an issue with the following sql:
SELECT count(*) as volume, wo_date,
CASE WHEN LOWER(myvar)='a' THEN col1
WHEN LOWER(myvar)='b' THEN col2 END AS field1
FROM table
GROUP BY wo_date,
CASE WHEN LOWER(myvar)='a' THEN col1
WHEN LOWER(myvar)='b' THEN col2 END
This does not work because of the LOWER function not being recognised as the same function in the SELECT (as you explained earlier).
So, you suggested I use a nested table (or a CTE).
But I cannot see how the above would be converted into a nested table because if you add the count(*) into the nested table then you'll have to add the CASE statement into a GROUP BY which will give me the same issue I had originally. Does that make sense?
Maybe if you could please convert above into a nested table expression with the count(*) it will become clear for me.
Thanks a lot for your help, apologies for the confusion.
|
|

10-14-08, 05:39
|
|
Registered User
|
|
Join Date: Sep 2004
Location: Belgium
Posts: 1,079
|
|
Quote:
|
Originally Posted by chesl73
SELECT count(*) as volume, wo_date,
CASE WHEN LOWER(myvar)='a' THEN col1
WHEN LOWER(myvar)='b' THEN col2 END AS field1
FROM table
GROUP BY wo_date,
CASE WHEN LOWER(myvar)='a' THEN col1
WHEN LOWER(myvar)='b' THEN col2 END
|
This is functionally equivalent to:
Code:
WITH t(wo_date,field1) AS
(SELECT wo_date,
CASE WHEN LOWER(myvar)='a' THEN col1
WHEN LOWER(myvar)='b' THEN col2 END
FROM table)
SELECT count(*) as volume, wo_date, field1
FROM t
GROUP BY wo_date, field1
__________________
--_Peter Vanroose,
__IBM Certified Database Administrator, DB2 9 for z/OS
__IBM Certified Application Developer
__ABIS Training and Consulting
__http://www.abis.be/
|
|

10-14-08, 06:43
|
|
Registered User
|
|
Join Date: Oct 2008
Posts: 19
|
|
Looking at your example it all seems so simple!
Thanks a lot for your time Peter.
|
|

10-14-08, 07:02
|
|
Registered User
|
|
Join Date: Jan 2007
Location: Jena, Germany
Posts: 2,662
|
|
Using the same function in a GROUP BY as in the SELECT list will definitively not work if the function is non-deterministic. The reason is that the grouping may be done on different values than what is produced in the SELECT list.
I am not sure if LOWER counts as deterministic or not (LCASE does).
__________________
Knut Stolze
IBM DB2 Analytics Accelerator
IBM Germany Research & Development
|
|
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|