June 29, 2006 at 4:11 pm
I have been working on this code for a couple hours now, so please excuse the possible typos. The only way I could find to handle a MULTI case statement was to write two case statements. I need to check the values in app and UserID. I got that to work with this code:
SELECT [Start Date], SUM(Volume),
CASE
WHEN Application = 'APP1' THEN
CASE UserID
WHEN '1' THEN 'P'
WHEN '2' THEN 'R'
WHEN '3' THEN 'R'
ELSE 'UNKNOWN'
END
ELSE
CASE
WHEN Application <> 'APP1' THEN 'V'
ELSE 'UNKNOWN'
END
END AS 'DType'
FROM ...
Now the issue is, I want to add the following syntax GROUP BY [Start Date], 'DType'... but it is stating that USERID and APP1 are not part of the aggregate. Yet those values are not returned the recordset.
Any help would be appreciated... this is fustrating me, and seems simple.
June 29, 2006 at 4:16 pm
If you have an expression generating a column in the resultset, and you need to GROUP BY the expression, you need to replicate all the code for the expression.
An alternative is to embed the expression in a derived table, and perform the aggregation in the outer SELECT:
SELECT [Start Date], DType, Sum(Volume)
FROM
--Create a derived table that handles the DType expression
(
SELECT
[StartDate],
Volume,
CASE UserID
WHEN '1' THEN 'P'
-- etc etc
END As DType
FROM YourTable
WHERE ...
) dt
GROUP BY [StartDate], DType
June 29, 2006 at 4:19 pm
Thank you for the quick response... I tried that and in my WHERE clause I am using an IN statement which uses ('V1',V2','V3') etc... and SQL doesn't like the double paren at the end... any work arounds?
June 29, 2006 at 4:21 pm
You are trying to hardcode business rules. What must be done UNDER NO CIRCUMSTANCES.
You must create table User_DType:
CREATE TABLE User_DType (
UserId int,
DType nvarchar(30)
)
INSERT INTO User_DType (UserId, DType)
SELECT 1, 'P'
UNION
SELECT 2, 'R'
UNION
SELECT 3, 'R'
SELECT ..., ISNULL(UT.DType, 'UNKNOWN')
FROM ...
LEFT JOIN User_DType UT ON UT.UserId = [main table].UserId
_____________
Code for TallyGenerator
June 29, 2006 at 4:24 pm
Ahhh... I forgot to name the derived table (DT)
Thanks...
June 29, 2006 at 4:31 pm
May of jump the gun a little bit... the subquery usually took 1min 10sec to run... I added the outside select statement and the group by statements and finally killed the query after 4 minutes of not receiving anything.
So, I added the DT after the subquery... do I need to create a table, or add a # sign before it. I haven't worked with derived or temp tables often.
June 29, 2006 at 4:35 pm
Serigy,
Unfortunately, I only have read rights to this server and I did not see the reason to have a table create when there will only be the three values V1, V2, and V3. I know you stated UNDER NO CIRCUMSTANCES, but logically, can I work around it?
June 29, 2006 at 4:59 pm
If you have only read rights how can you create or alter SP?
If you have rights to run ad-hoc queries only (I better keep silence about such "smart" sequrity model, just not to be rude) you may have this look-up table in your query:
INNER JOIN (select 1 as UserId, 'P' as DType UNION SELECT .... ) UT ON UT.UserId = ...
_____________
Code for TallyGenerator
June 30, 2006 at 12:51 am
Why don't you use this one
CASE
WHEN Application+UserID = 'APP11' THEN 'P'
WHEN Application+UserID in 'APP12' THEN 'R'
WHEN Application+UserID in 'APP13' THEN 'R'
ELSE 'UNKNOWN'
If UserID is a number you need to convert the number in varchar like this
ltrim(rtrim(str(UserID ))) to avoid extra spaces
The general idea is to user a string concatenation insead to test single values.
Hope this help.
Claudia
June 30, 2006 at 1:06 am
I reformated your code to be easier to understand, and this is what I got
SELECT [Start Date],
SUM(Volume),
CASE
WHEN Application = 'APP1' THEN
CASE UserID
WHEN '1' THEN 'P'
WHEN '2' THEN 'R'
WHEN '3' THEN 'R'
ELSE 'UNKNOWN' -- No need for the ELSE here. Could be taken care of later.
END
ELSE
CASE
WHEN Application <> 'APP1' THEN 'V' -- Redundant since Application already is <> 'App1'.
ELSE 'UNKNOWN' -- The only reason for this case to occur is when Application is NULL. True?
END
END AS 'DType'
FROM ...
There is a lot of redundant code, so this is my suggestion to your problem.
SELECT z.[Start Date],
z.DType,
SUM(z.Volume)
FROM (
SELECT [Start Date],
Volume,
CASE
WHEN Application = 'APP1' AND UserID = '1' THEN 'P'
WHEN Application = 'APP1' AND UserID = '2' THEN 'R'
WHEN Application = 'APP1' AND UserID = '3' THEN 'R'
WHEN Application <> 'APP1' THEN 'V'
ELSE 'UNKNOWN'
END DType
FROM ...
) z
GROUP BY z.[Start Date],
z.DType
ORDER BY z.[Start Date],
z.DType
N 56°04'39.16"
E 12°55'05.25"
June 30, 2006 at 1:10 am
This will potentially lead to wrong results. What when Application + UserID is 'App131'?
Is that Application 13 and User 1, or Application 1 and User 31?
N 56°04'39.16"
E 12°55'05.25"
June 30, 2006 at 5:23 am
We can shorten the code still further. But I'm just riding Peso's suggestion...
SELECT z.[Start Date],
z.DType,
SUM(z.Volume)
FROM (
SELECT [Start Date],
Volume,
CASE
WHEN Application = 'APP1' AND UserID = '1' THEN 'P'
WHEN Application = 'APP1' AND UserID IN ('2', '3') THEN 'R'
WHEN Application <> 'APP1' THEN 'V'
ELSE 'UNKNOWN'
END DType
FROM ...
) z
GROUP BY z.[Start Date],
z.DType
ORDER BY z.[Start Date],
z.DType
Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
June 30, 2006 at 6:59 am
A compromise between
1. a lookup table with app,user,dtype (which would involve some odd joins anyway with the <> and the ELSE) and
2. just putting a slab of code in your proc (which means information is buried where you can't find it, and you effectively have denormalised 'data' since the same (or what should be the same!) mapping may be specified in more than one place)
would be to put this CASE statement in a scalar UDF. That way you can clearly identify the purpose of the code, you can find it when you need to, and you can change it in just one place when necessary (which it will be, given time), rather than trawling through every procedure looking for this bit of logic. Still, the actual data mappings should still preferably be in a table, as you might need to report on them - or on time-dependent versions of them, etc...(i.e. they are data and should be in a database).
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
June 30, 2006 at 8:32 am
Peter,
June 30, 2006 at 9:20 am
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
Viewing 15 posts - 1 through 15 (of 17 total)
You must be logged in to reply to this topic. Login to reply