Showing posts with label expression. Show all posts
Showing posts with label expression. Show all posts

Monday, March 26, 2012

grouping by partial string

Hello All,

I am looking for an expression for a group in a matric. I am trying to figure out how to group by the a certain amount of letters in a string. For example if I have the followong fields I am grouping...

Bob001

Bob

Robert005

Doug053

Doug100

Douglas

Barney001

Frank

I want to group it up as...

Bob

Doug

Barney

Frank

And then be able to summarize the results in the matrix.

Thanks in advance for any help

-Clint

If the last 3 characters are always 3 digits then you can simply group by left(Name, len(Name) - 3)

Adamus

|||

Just be sure your SELECT left(Name, len(Name) - 3) contains the trim.

Adamus

|||Unfortunately they do not all end in 3 digits. Ill fix my example. thanks though|||

Ok next question:

If digits exist, will they always be 3 digits on the tail end of the name?

If so you can check CASE Name WHEN isnumeric(right(Name, 3)) ...

If not, you'll probably want to use regular expressions to grab the text only portion.

In that case, you'll have to create a UDF which you can find here

Adamus

|||

Thanks Adamus,

Yes, when there are numbers present at the end, there are always three.

What would the expression look like?

Thanks much

Clint

|||

CREATETABLE #temp(myName varchar(20))

INSERTINTO #temp SELECT'Bob001'

INSERTINTO #temp SELECT'Bob'

INSERTINTO #temp SELECT'Robert001'

INSERTINTO #temp SELECT'Robert'

SELECT*FROM

(

SELECTCASEWHENISNUMERIC(RIGHT(myName, 3))= 1

THENLEFT(myName,LEN(myName)- 3)ELSE myName ENDAS [Result]

FROM #temp

)as t

GROUPBY Result

DROPTABLE #temp

Adamus

|||

What happened to Robert in the second list? Was he fired? Did he quit?

On A serious note, someone posted the code you need to remove the digits...

though it does not appear that it will solve the problem as "Douglas" has no digits on the end of it.

What you are looking for, sounds to me is some type of pattern matching...

|||

nice touch.. Mr. Turner...

I hope he actually uses the correct sql to do a select into the temp table instead of doing it all literally.

|||Thanks for the help. I am trying to accomplish in reporting services itself, not in the dbase. From what I gather there is now expression that would do the same thing. Again,I appreciate the help.|||

You can do this in SQL in the DataSet instead of the database or you can do in an expression using the Len function to find out how long the initial string is, the InStr function to find the location of a number, and then the Mid function to extract a string that is the Total Length long minus the Index value of the number that was found. Wrap all this in an IIF to handle the cases when no number is present.

HTH

Dean

|||

After regrouping at another field that seperated out the fields ending in - 083, i was able to get it working with your expression modified. Thanks so much for your help. Here is what ended up working...

Code Snippet

=iif(Fields!BankNumber.Value="083",left(Fields!TestName.Value, len(Fields!TestName.Value) - 11),Fields!TestName.Value)

|||oops. turns out not to work quite right after all. I errors out the first field name but works for the rest. I get a warning saying that the Length statement must be equal to or greater than 0. Since we are using a negative number, it is popping a warning.|||

Exactly. Im trying to figure out how to trim the last 11 characters off certain fields. My real life example has some fields ending in - Bank 083 (or another 3 numbers). i am thinking of the "LIKE" to seach for the pattern and remove it for group sake. Anyone have an idea on that one?

Thanks,

Clint

Friday, March 23, 2012

Grouping by Age

I have a table Age and need to create Report by Grouping Salesfigures according to Age.
I put the following expression into Grouping and Sorting Properties/General/Filter /Sorting Expression... as well as in Textbox Properties/ values..

=IIF(Fields!Age.Value < 16, "<16",IIF(Fields!Age.Value <21,"16-20")

Errormessage: Value expression for textbox "Age" error: Argument not specified for parameter 'FalsePart' of 'Public function IIF(Expression as Boolean, TruePart as Object, Falsepart As Object) As Object'.

Question 2 .
How to return Month as January, February... In correct order?
"DATENAME(mm, Sales.time) AS Month" (Ascending ) returns starting with April, August...
DATEPART(mm, Sales.time) AS Month (Ascending ) returns starting with 1, 10, 11 ...

Answer 1

Your expression is incomplete. As the error message says, you are missing the FlasePart of the nested Iif function, as well a parentheses

=IIF(Fields!Age.Value < 16, "<16",IIF(Fields!Age.Value <21,"16-20", ">20" ) )

Can you clarify Quaestion 2. E.g. where are you putting this code, can you paste your query?

|||

For Question 1 you don't have a false path to follow in your second iif.

=IIF(Fields!Age.Value < 16, "<16",IIF(Fields!Age.Value <21,"16-20",""))

|||Thank you so much!

SELECT SUM(Cd.Price) AS Sales, DATENAME(mm, Purchase.time) AS Month, Staff.Name
FROM Staff INNER JOIN
Purchase ON Staff.Staff_id = Purchase.Salesperson_id INNER JOIN
Cd ON Purchase.Cd_id = Cd.Cd_id
GROUP BY DATENAME(mm, Purchase.time), Staff.Name
ORDER BY Month Asc

The outcome is starting with April...
(not with January)?|||Thank you.. still, "Argument not specified for false part". Something I've misunderstood?

=IIF(Fields!Age.Value < 16, "<16",IIF(Fields!Age.Value <21,"16-20"),IIF(Fields!Age.Value <31,"21-30"), IIF(Fields!Age.Value < 41,"31-40"),IIF(Fields!Age.Value <51,"41-50",">50"))

I put this value expression In textbox "Age"/Expression, as well as in Grouping Sorting properties /General/Filter/ Sorting|||

Yes you have misunderstood this slightly. The definition of the Iif function is

Iif(<<condition>>, TruePart, FalsePart)

Your expression puts many Iif's all passed into a single Iif. You actually have to nest the Iif's as the FalsePart of the previous Iif

Your expression:
=IIF
( Fields!Age.Value < 16 <- condition
, "<16" <- TruePart
, IIF(Fields!Age.Value <21,"16-20") <- FalsePart nested IIF
, IIF(Fields!Age.Value <31,"21-30") <- Error 4th argument
, IIF(Fields!Age.Value <41,"31-40") <- Error 5th argument
, IIF(Fields!Age.Value <51,"41-50",">50") <- Error 6th argument
)

Correct Expression:
=IIF
( Fields!Age.Value < 16 <- condition
, "<16" <- TruePart
, IIF <- FalsePart nested IIF
( Fields!Age.Value < 21 <- condition
,"16-20" <- TruePart
, IIF <- FalsePart nested IIF
( Fields!Age.Value < 31 <- condition
, "21-30" <- TruePart
, IIF <- FalsePart nested IIF
( Fields!Age.Value < 41 <- condition
, "31-40" <- TruePart
, IIF <- FalsePart nested IIF
( Fields!Age.Value < 51 <- condition
, "41-50" <- TruePart
, ">50" <- FalsePart
)
)
)
)
)

just make sure you get the parentheses right and you remove the comments

|||

As far as your query goes, display the name but order by number. for this to work you must include both in the GROUP BY clause

SELECT SUM(Cd.Price) AS Sales, DATENAME(mm, Purchase.time) AS Month, Staff.Name
FROM Staff INNER JOIN
Purchase ON Staff.Staff_id = Purchase.Salesperson_id INNER JOIN
Cd ON Purchase.Cd_id = Cd.Cd_id
GROUP BY DATENAME(mm, Purchase.time)
, DATEPART(mm, Purchase.time)
, Staff.Name
ORDER BY DATEPART(mm, Purchase.time) Asc

|||

Would it be possible to create a field from a select e.g.

SELECT Age, AgeGroup =

CASE

WHEN (age >= 1 and age <= 3) THEN 'Age 1-3'

WHEN (age >= 4 and age <= 5) THEN 'Age 4-5'

WHEN (age >= 6 and age <= 7) THEN 'Age 6-7'

ELSE 'Over age'

END

FROM tblAge

|||In fact, I prefer this option, give RS less work to do.

Wednesday, March 21, 2012

Group sum outside group?

I'm trying to get a sum of values from a group with the following expression.
=SUM(Fields!BF_Child.Value, "table1_Details_Group"). When I try to run it I
get the following error.
[rsInvalidAggregateScope] The Value expression for the textbox â'textbox7â'
has a scope parameter that is not valid for an aggregate function. The scope
parameter must be set to a string constant that is equal to either the name
of a containing group, the name of a containing data region, or the name of a
data set.
Build complete -- 1 errors, 0 warnings
Why can't I sum group values?Eric,
Try this:
=RunningValue(Fields!BF_Child.Value,Sum,"table1_Details_Group")
Michael C
"eric" wrote:
> I'm trying to get a sum of values from a group with the following expression.
> =SUM(Fields!BF_Child.Value, "table1_Details_Group"). When I try to run it I
> get the following error.
> [rsInvalidAggregateScope] The Value expression for the textbox â'textbox7â'
> has a scope parameter that is not valid for an aggregate function. The scope
> parameter must be set to a string constant that is equal to either the name
> of a containing group, the name of a containing data region, or the name of a
> data set.
> Build complete -- 1 errors, 0 warnings
>
> Why can't I sum group values?|||Hi Michael,
Thank you for the response. Unfortunately I get the same error. I have 2
groups, one to group by parent and the second group to reduce duplicate
records. The Sum I would like to total the second group values, but only
the visible records in the group. Any other ideas? Thanks
Eric
"Michael C" wrote:
> Eric,
> Try this:
> =RunningValue(Fields!BF_Child.Value,Sum,"table1_Details_Group")
> Michael C
> "eric" wrote:
> > I'm trying to get a sum of values from a group with the following expression.
> > =SUM(Fields!BF_Child.Value, "table1_Details_Group"). When I try to run it I
> > get the following error.
> >
> > [rsInvalidAggregateScope] The Value expression for the textbox â'textbox7â'
> > has a scope parameter that is not valid for an aggregate function. The scope
> > parameter must be set to a string constant that is equal to either the name
> > of a containing group, the name of a containing data region, or the name of a
> > data set.
> > Build complete -- 1 errors, 0 warnings
> >
> >
> > Why can't I sum group values?|||Hi Eric,
Did you find the solution for this?
I have the same problem and I would like to know if there´s anyway of doing
it.
Thanks,
Mónica
"eric" <eric@.discussions.microsoft.com> escribió en el mensaje
news:2DD05D4D-4B91-4088-B1A9-EA5BF35592B4@.microsoft.com...
> Hi Michael,
> Thank you for the response. Unfortunately I get the same error. I have 2
> groups, one to group by parent and the second group to reduce duplicate
> records. The Sum I would like to total the second group values, but only
> the visible records in the group. Any other ideas? Thanks
> Eric
> "Michael C" wrote:
>> Eric,
>> Try this:
>> =RunningValue(Fields!BF_Child.Value,Sum,"table1_Details_Group")
>> Michael C
>> "eric" wrote:
>> > I'm trying to get a sum of values from a group with the following
>> > expression.
>> > =SUM(Fields!BF_Child.Value, "table1_Details_Group"). When I try to
>> > run it I
>> > get the following error.
>> >
>> > [rsInvalidAggregateScope] The Value expression for the textbox
>> > 'textbox7'
>> > has a scope parameter that is not valid for an aggregate function. The
>> > scope
>> > parameter must be set to a string constant that is equal to either the
>> > name
>> > of a containing group, the name of a containing data region, or the
>> > name of a
>> > data set.
>> > Build complete -- 1 errors, 0 warnings
>> >
>> >
>> > Why can't I sum group values?sql

group sum

I have a table with groups. I have a detail field (textbox66) that has the
following expression:
=iif(Fields!endDate.Value = Nothing, 1, iif(Fields!endDate.Value <
dateadd("d", 14, Parameters!startDate.Value), 0, 1))
I need to have a field in the group footer sum this column. How do I do
this? If I do =Sum(ReportItems!textbox66.value) in a group footer field, I
get the following errors:
Aggregate functions can be used only on report items contained in page
headers and footers.
AND
Report Item expressions can only refer to other report items within the same
grouping scope or a containing grouping scope.Just use this expression for the group footer:
=Sum(iif(IsNothing(Fields!endDate.Value), 1, iif(Fields!endDate.Value <
dateadd("d", 14, Parameters!startDate.Value), 0, 1)))
-- Robert
This posting is provided "AS IS" with no warranties, and confers no rights.
"SharinDenver" <SharinDenver@.discussions.microsoft.com> wrote in message
news:CC1EE200-443F-45B8-95CA-08FEFF2941C6@.microsoft.com...
>I have a table with groups. I have a detail field (textbox66) that has the
> following expression:
> =iif(Fields!endDate.Value = Nothing, 1, iif(Fields!endDate.Value <
> dateadd("d", 14, Parameters!startDate.Value), 0, 1))
> I need to have a field in the group footer sum this column. How do I do
> this? If I do =Sum(ReportItems!textbox66.value) in a group footer field,
> I
> get the following errors:
> Aggregate functions can be used only on report items contained in page
> headers and footers.
> AND
> Report Item expressions can only refer to other report items within the
> same
> grouping scope or a containing grouping scope.

Group Sort By Expression

What is the syntax to sort on a group. For example:
If group = 1 then sort by field1 ascending
If group = 2 then sort by field2 ascending
If group = 3 then sort by field3 descending
Thanks!There are a couple ways You could write this.
If your "Group" selection is a integer:
=Choose(Parameters!Group.Value,Fields!Field1.Value,
Fields!Field2.Value,Fields!Fields3.Value)
Otherwise
=IIf(Parameters!Group.Value ='1',Fields!Fields1.Value,IIf(Parameters!Group.Value ='2',Fields!Field2.Value,Fields!Field3.Value))
Michael C
"Anonymous" wrote:
> What is the syntax to sort on a group. For example:
> If group = 1 then sort by field1 ascending
> If group = 2 then sort by field2 ascending
> If group = 3 then sort by field3 descending
> Thanks!|||What is the syntax though for desc vs asc.
"Michael C" wrote:
> There are a couple ways You could write this.
> If your "Group" selection is a integer:
> =Choose(Parameters!Group.Value,Fields!Field1.Value,
> Fields!Field2.Value,Fields!Fields3.Value)
> Otherwise
> =IIf(Parameters!Group.Value => '1',Fields!Fields1.Value,IIf(Parameters!Group.Value => '2',Fields!Field2.Value,Fields!Field3.Value))
> Michael C
> "Anonymous" wrote:
> > What is the syntax to sort on a group. For example:
> >
> > If group = 1 then sort by field1 ascending
> > If group = 2 then sort by field2 ascending
> > If group = 3 then sort by field3 descending
> >
> > Thanks!|||On Aug 22, 12:32 pm, Anonymous <Anonym...@.discussions.microsoft.com>
wrote:
> What is the syntax to sort on a group. For example:
> If group = 1 then sort by field1 ascending
> If group = 2 then sort by field2 ascending
> If group = 3 then sort by field3 descending
> Thanks!
Right click the table/matrix control and select Properties. Select the
Groups tab, then select the 'Edit...' button for the Groups to set
sorting on. Then select the 'Sorting' tab and below 'Expression,'
select 'Fields!Field1.Value' and then below 'Direction,' select
'ascending.' Repeat this for the other groups as well. Hope this
helps.
Regards,
Enrique Martinez
Sr. Software Consultantsql

Monday, March 19, 2012

Group expression that calculate percentages.

I have an expression in a group that calculates percent of sales:

=iif(Sum(Fields!BOOKD.Value)=0,0,IIF(Sum(Fields!NET.Value)=0,0,((Sum(Fields!BOOKD.Value)-Sum(Fields!NET.Value))/Sum(Fields!BOOKD.Value))))*100

The problem I'm having is that if both the

Sum(Fields!BOOKD.Value)=0 and

Sum(Fields!NET.Value)=0 ,

the expression returns the message #ERROR instead of a 0.

I have the initial query set to display 0 if the value is null.

,SUM(ISNULL(R.BOOKD,0))BOOKD
,SUM(ISNULL(R.NET,0))NET

I would greatly appreciate any help on how to solve this issue.

Thank Barb

IIF is a VB runtime function call which evaluates all arguments. Therefore, in the case of BOOKD being 0, you will get a division by zero.

Please read the following related thread on options to solve this: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=188577&SiteID=1

-- Robert

group expression

Hello, I am very new to Reporting Services and want to do something I have
done in other programs using a tool or wizard. I want to group my data by "
30 days over due" , then " 60 days over due" etc..Based on the following
DAYSDUE > 30 and < 60
DAYSDUE > 60 and < 90
DAYSDUE > 90 and < 120
DAYSDUE > 120
I think it will need to be an expression in the group dialog box, but for
the life of me I cant's seem to come up with it. Any help would be
appreciated. ThanksTry this:
=iif(Fields!Daysdue.Value > 120, 1, iif(Fields!Daysdue.Value > 90, 2,
iif(Fields!Daysdue.Value > 60, 3, iif(Fields!Daysdue.Value > 30, 4, 5))))
The expression basically maps the integer values to five distinct groups: 1,
2, 3, 4, 5
-- Robert
This posting is provided "AS IS" with no warranties, and confers no rights.
"SLB" <SLB@.discussions.microsoft.com> wrote in message
news:D262B295-7A20-45F0-B6A4-1ADC448FD970@.microsoft.com...
> Hello, I am very new to Reporting Services and want to do something I have
> done in other programs using a tool or wizard. I want to group my data by
> "
> 30 days over due" , then " 60 days over due" etc..Based on the following
> DAYSDUE > 30 and < 60
> DAYSDUE > 60 and < 90
> DAYSDUE > 90 and < 120
> DAYSDUE > 120
> I think it will need to be an expression in the group dialog box, but for
> the life of me I cant's seem to come up with it. Any help would be
> appreciated. Thanks
>

Group Expression

I have a doubt on group expressions. Can anyone tell me the
significance of creating a group in a table where the group on
expression is =1?If you group on an expression like =1, you are grouping on a constant value.
Consequently, you will only get one group at runtime which contains all
data.
A grouping in RDL is similar to what a "group by" in a SQL query is doing -
it is grouping the data into groups based on the grouping value.
-- Robert
This posting is provided "AS IS" with no warranties, and confers no rights.
"Anishya" <anishya@.gmail.com> wrote in message
news:1127286499.682855.101660@.g44g2000cwa.googlegroups.com...
>I have a doubt on group expressions. Can anyone tell me the
> significance of creating a group in a table where the group on
> expression is =1?
>

Wednesday, March 7, 2012

Group By Expressions

I'd like to dynamically create a group by expression. I have

select sourcecd
FROM dbo.ITMV_ScanCardHistory
GROUP BY dbo.fn_GroupBy (@.GroupBy)

Where:

@.groupby = sourcecd and

fn_GroupBy =

CREATE FUNCTION dbo.fn_GroupBy
(@.ColumnName Varchar(55))
RETURNS Varchar(55)
AS
BEGIN

RETURN @.ColumnName
END

I keep getting this error message:

Server: Msg 164, Level 15, State 1, Line 48
GROUP BY expressions must refer to column names that appear in the select list.

Please help.

Hello,

This won't work as the Group By clause is looking for a column name, whereas you are supplying a varchar(55) string...

Have you looked at dynamic statements via ExecuteSQL?

Have a look at EXECUTE in BOL.

Cheers

Rob

|||

The error is saying that what you have in your GROUP by you need in your select.

Why do you want to do this, there are a number of options but I would like to understand why you need this first.

|||thank you. We are designing reports in reporting services and we'd like to give the business user the option of selection which column they'd like to group their data by.|||

thanks, however SQL Books says that scalar functions or any valid expression can be used in a group by:

see "

Invoking User-Defined Functions That Return a Scalar Value"

under Accessing and Changing Relation...

|||

You can do it in RS by making the group by field dynamic. In your group define the field to group by as fields(Paramaters("GroupBy").Value).Value

Or something like that

|||Thank you, I will give this a try.|||

Hi,

By using sp_executesql you can create your dynamic sql and run it as below

declare @.sql as nvarchar(1000)
SELECT @.sql = N'
select ' + dbo.fn_GroupBy('eventid') +
N' FROM Events
GROUP BY ' + dbo.fn_GroupBy('eventid')

-- SELECT @.sql

exec sp_executesql @.sql

But you can also use "distinct" instead of "group by"


declare @.sql as nvarchar(1000)
SELECT @.sql = N'
select distinct ' + dbo.fn_GroupBy('eventid') + N' FROM Events '
-- SELECT @.sql

exec sp_executesql @.sql

Eralper

http://www.kodyaz.com

Group By Error Under SQL 2005

Our stored procedure throws the following error when running on 2005
w/compatibility set to 90, but not 80:
"Each GROUP BY expression must contain at least one column that is not an
outer reference. Severity 15, State 1, Procedure "procname", line 351"
The code in question is:
....
OR
(EXISTS (SELECT e.logical_seat_row, b.logical_seat_num, count(*)
FROM #ZoomSet e
WHERE e.logical_seat_num >= b.logical_seat_num
and e.logical_seat_num <= c.logical_seat_num
and e.bit_col & 64 = 64
and e.logical_seat_row = b.logical_seat_row
GROUP BY e.logical_seat_row, b.logical_seat_num
HAVING count(*) >= @.num_wc_ind))
)
.....
I've searched support.msft.com, as well as this newsgroup, and all of the
web, but can't find this error anywhere. Any ideas would be appreciated.
Thanks!
Steven Bras
Tessitura Network, Inc.>> Our stored procedure throws the following error when running on 2005 w/co
mpatibility set to 90, but not 80:: "Each GROUP BY expression must contain a
t least one column that is not an outer reference. Severity 15, State 1, Pr
ocedure "procname", line 35
1" <<
As best I can tell from the fragment posted, the code lookd fine from a
standards viewpoint (ignoring the bit operator crap). I would clean it
up for human use (one BETWEEN is easier to read and understand than two
comparisons) and see if that helps.
Since it is an EXISTS() predicate, use the * instead of a list; my
thought is that the engine might be trying to build the list when all
it needs to do is find is one row.
OR
(EXISTS (SELECT *
FROM #ZoomSet AS E
WHERE E.logical_seat_num
BETWEEN B.logical_seat_num
AND C.logical_seat_num
AND E.bit_col & 64 = 64
AND E.logical_seat_row = B.logical_seat_row
GROUP BY E.logical_seat_row, B.logical_seat_num
HAVING COUNT (*) >= @.num_wc_ind))
)
The other things are to re-write the whole query to get rid of the
temp table and the assembly language bit fiddling.
It looks like you are trying to find a block of vacant seats on the
same row. Ihave queries for that in SQL FOR SMARTIES which are
simpler.|||Thanks; I do appreciate your response and am a long-standing admirer of your
columns and books.
But why does the error now occur under 2005 where it didn't used to under
SQL 2000?
--
Steven Bras
Tessitura Network, Inc.
"--CELKO--" wrote:

351" <<
> As best I can tell from the fragment posted, the code lookd fine from a
> standards viewpoint (ignoring the bit operator crap). I would clean it
> up for human use (one BETWEEN is easier to read and understand than two
> comparisons) and see if that helps.
> Since it is an EXISTS() predicate, use the * instead of a list; my
> thought is that the engine might be trying to build the list when all
> it needs to do is find is one row.
> OR
> (EXISTS (SELECT *
> FROM #ZoomSet AS E
> WHERE E.logical_seat_num
> BETWEEN B.logical_seat_num
> AND C.logical_seat_num
> AND E.bit_col & 64 = 64
> AND E.logical_seat_row = B.logical_seat_row
> GROUP BY E.logical_seat_row, B.logical_seat_num
> HAVING COUNT (*) >= @.num_wc_ind))
> )
> The other things are to re-write the whole query to get rid of the
> temp table and the assembly language bit fiddling.
> It looks like you are trying to find a block of vacant seats on the
> same row. Ihave queries for that in SQL FOR SMARTIES which are
> simpler.
>|||> But why does the error now occur under 2005 where it didn't used to under
> SQL 2000?
In the Books Online topic 'sp_dbcmptlevel', it states the following:
Compatibility level setting of 80 A GROUP BY clause in a subquery that
references a column from the outer query succeeds.
Compatibility level setting of 90 A GROUP BY clause in a subquery that
references a column from the outer query returns an error as per the SQL
standard.
Gail Erickson [MS]
SQL Server Documentation Team
This posting is provided "AS IS" with no warranties, and confers no rights
Download the latest version of Books Online from
http://www.microsoft.com/technet/pr...oads/books.mspx
"StevenBr" <sbras@.community.nospam> wrote in message
news:ACFBFA3A-8CAF-4875-A83F-38607B5BDC23@.microsoft.com...
> Thanks; I do appreciate your response and am a long-standing admirer of
> your
> columns and books.
> But why does the error now occur under 2005 where it didn't used to under
> SQL 2000?
> --
> Steven Bras
> Tessitura Network, Inc.
>
> "--CELKO--" wrote:
>|||n Mon, 26 Jun 2006 17:39:15 -0700, "Gail Erickson [MS]"
<gaile@.online.microsoft.com> wrote:

> In the Books Online topic 'sp_dbcmptlevel', it states the following:
>Compatibility level setting of 80 A GROUP BY clause in a subquery that
>references a column from the outer query succeeds.
>Compatibility level setting of 90 A GROUP BY clause in a subquery that
>references a column from the outer query returns an error as per the SQL
>standard.
Interesting.
It may also be worth pointing out why this would be so. Any reference
within the subquery that refers to the outer query is, for the purpose
of the subquery, a reference to a constant. And there is no reason to
include a constant in a GROUP BY list.
In the specific example posted:

>....
> OR
> (EXISTS (SELECT e.logical_seat_row, b.logical_seat_num, count(*)
> FROM #ZoomSet e
> WHERE e.logical_seat_num >= b.logical_seat_num
> and e.logical_seat_num <= c.logical_seat_num
> and e.bit_col & 64 = 64
> and e.logical_seat_row = b.logical_seat_row
> GROUP BY e.logical_seat_row, b.logical_seat_num
> HAVING count(*) >= @.num_wc_ind))
> )
>.....
it is the reference to b.logical_seat_num in the GROUP BY that is
redundant, since there can be only one value for any given evaluation
of the subquery. But we can go farther and observe that since
e.logical_seat_row = b.logical_seat_row, the reference to
e.logical_seat_row in the GROUP BY is also redundant.
Which means the entire GROUP BY clause is not required, as they
resolve to a single row, and since (as has already been pointed out)
the SELECT list for an EXISTS subquery should be *, the GROUP BY
should be redundant... BUT WAIT! Will it be legal to have a HAVING
clause reference an aggregate expression COUNT when the select list is
an *? Good question, I'm not sure.
--Quick test in 2000 and 2005, using system tables, demonstrates that
--it works!
select *
from sysobjects
where exists
(select * from syscolumns
where syscolumns.id = sysobjects.id
having count(*) > 30)
But it still looks funny to my sensitive nature. I think it might be
safer to rewrite without the EXISTS:
OR
(@.num_wc_ind <=
(SELECT count(*)
FROM #ZoomSet e
WHERE e.logical_seat_num >= b.logical_seat_num
and e.logical_seat_num <= c.logical_seat_num
and e.bit_col & 64 = 64
and e.logical_seat_row = b.logical_seat_row)
)
Roy Harvey
Beacon Falls, CT|||Hi,
Just checking in to see if the suggestions were helpful. Please let us know
if you would like further assistance.
Have a great day!
+++++++++++++++++++++++++++
Charles Wang
Microsoft Online Partner Support
+++++++++++++++++++++++++++
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
========================================
=============
Business-Critical Phone Support (BCPS) provides you with technical phone
support at no charge during critical LAN outages or "business down"
situations. This benefit is available 24 hours a day, 7 days a w to all
Microsoft technology partners in the United States and Canada.
This and other support options are available here:
BCPS:
https://partner.microsoft.com/US/te...erview/40010469
Others:
https://partner.microsoft.com/US/te...upportoverview/
If you are outside the United States, please visit our International
Support page:
http://support.microsoft.com/defaul...rnational.aspx.
========================================
=============
This posting is provided "AS IS" with no warranties, and confers no rights.

Sunday, February 26, 2012

GROUP BY column-name problem (need expression)

Please advise on how to get the GROUP BY coded in an acceptable way:

DECLARE @.LO INT
DECLARE @.HI INT
DECLARE @.StartDate varchar(10)
DECLARE @.EndDate varchar(10)

SELECT @.StartDate = '01/01/2005'
SELECT @.EndDate = '06/30/2005'
SELECT @.LO= 250
SELECT @.HI= 333

SELECT
StateCD
, CountyCD
, Zip
, Z.CityName
, Z.StateCode
, Z.CountyName
, 'Criteria' = 'JumboRange:' + Convert(varchar(4),@.LO) + '-' +
Convert(varchar(4),@.HI)
, 'StartingDate' = @.StartDate
, 'ThruDate' = @.EndDate
, JumboAmount = SUM(JumboAmount)
, JumboMortgages = SUM(JumboMortgages)
, JumboFIXMortgages= SUM(JumboFIXMortgages)
, JumboFIXAmount = SUM(JumboFIXAmount)
, JumboARMMortgages = SUM(JumboARMMortgages)
, JumboARMAmount= SUM(JumboARMAmount)
FROM LoanDetails T INNER JOIN dbo.ZipCodesPreferred Z
ON T.StateCD = Z.FIPS_State AND T.CountyCD = Z.FIPS_County AND T.Zip =
Z.ZipCode
GROUP BY
StateCD
, CountyCD
, Zip
, Z.CityName
, Z.StateCode
, Z.CountyName
, 'Criteria' = 'JumboRange:' + Convert(varchar(4),@.LO) + '-' +
Convert(varchar(4),@.HI)
, 'StartingDate' = @.StartDate
, 'ThruDate' = @.EndDateYou don't need the non-column expressions in the GROUP BY list. Column
aliases aren't permitted either. Try:

...
GROUP BY statecd, countycd, zip, Z.cityname, Z.statecode, Z.countyname

--
David Portas
SQL Server MVP
--|||Here is how a SELECT works in SQL ... at least in theory. Real
products will optimize things, but the code has to produce the same
results.

a) Start in the FROM clause and build a working table from all of the
joins, unions, intersections, and whatever other table constructors are
there. The <table expression> AS <correlation name> option allows you
give a name to this working table which you then have to use for the
rest of the containing query.

b) Go to the WHERE clause and remove rows that do not pass criteria;
that is, that do not test to TRUE (i.e. reject UNKNOWN and FALSE). The
WHERE clause is applied to the working set in the FROM clause.

c) Go to the optional GROUP BY clause, make groups and reduce each
group to a single row, replacing the original working table with the
new grouped table. The rows of a grouped table must be group
characteristics: (1) a grouping column (2) a statistic about the group
(i.e. aggregate functions) (3) a function or (4) an expression made up
those three items.

d) Go to the optional HAVING clause and apply it against the grouped
working table; if there was no GROUP BY clause, treat the entire table
as one group.

e) Go to the SELECT clause and construct the expressions in the list.
This means that the scalar subqueries, function calls and expressions
in the SELECT are done after all the other clauses are done. The
"AS" operator can also give names to expressions in the SELECT
list. These new names come into existence all at once, but after the
WHERE clause, GROUP BY clause and HAVING clause has been executed; you
cannot use them in the SELECT list or the WHERE clause for that reason.

If there is a SELECT DISTINCT, then redundant duplicate rows are
removed. For purposes of defining a duplicate row, NULLs are treated
as matching (just like in the GROUP BY).

f) Nested query expressions follow the usual scoping rules you would
expect from a block structured language like C, Pascal, Algol, etc.
Namely, the innermost queries can reference columns and tables in the
queries in which they are contained.

g) The ORDER BY clause is part of a cursor, not a query. The result
set is passed to the cursor, which can only see the names in the SELECT
clause list, and the sorting is done there. The ORDER BY clause cannot
have expression in it, or references to other columns because the
result set has been converted into a sequential file structure and that
is what is being sorted.

As you can see, things happen "all at once" in SQL, not "from left to
right" as they would in a sequential file/procedural language model. In
those languages, these two statements produce different results:
READ (a, b, c) FROM File_X;
READ (c, a, b) FROM File_X;

while these two statements return the same data:

SELECT a, b, c FROM Table_X;
SELECT c, a, b FROM Table_X;

Think about what a confused mess this statement is in the SQL model.

SELECT f(c2) AS c1, f(c1) AS c2 FROM Foobar;

That is why such nonsense is illegal syntax.