Showing posts with label functions. Show all posts
Showing posts with label functions. Show all posts

Monday, March 19, 2012

Aggregete() function doesn't work for SQL query results!

Reporting Services translates null value into blank on SQL query results, but not on MDX query results. But Aggregate() functions is triggered only by null value.

So Aggregate() function only works for MDX query results, not for SQL query results.

MDX example:

select {[Measures].[Sales]} on columns,

{[Account].[Hierarchy].Members} on rows

FROM Cube

SQL example:

SELECT * FROM OPENQUERY(Linked_Cube, '
select {[Measures].[Sales]} on columns,

{[Account].[Hierarchy].Members} on rows

FROM Cube')

Now you build a report with a table, then add a grouping and use "=Aggregate(Fields!Sales.Value)" for the group level cell. If you bind MDX query to this table, then aggregates show up correctly. But if you bind SQL query to this table, there are no aggregates at all.

I need to use SQL query to drive my reports, because MDX query results need to be merged with results from other calculations.

How can I make Aggregate() function to work for SQL query results?

Thanks,

Bo Dong

bo_dong@.yahoo.com

How can I make it to work for SQL as well?

Please read my answer on your other thread: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=668524&SiteID=1

-- Robert

Sunday, March 11, 2012

Aggregation functions in Calculated Measures displays wrong values.

Hi,

I think this calculated measure implementation is making me absent minded, so if this seems like a silly question, please ignore my behaviour but do answer to my post :-)

I will ask this question with a sample data: consider that the cube consists of School Children's names as the first dimension (school_children) and date(jan, feb....) as the second dimension. the measure (M) is the 'exam scores' of the school children.

jan feb mar
school_children M M M
--
tony 50 20 40
bony 10 40 40
mony 60 60 70

Now when i add a calculated measure where I want to display the avg marks of each. so in the calculated measures formula I add: Avg([Measures].[M]). (This is how it is in the Oracle OLAP :-))

But this does not display the average of all tony's scores in a new column M2 (calculated measure). it just displays the same values as the measure M.

so what is happening here? how to get the average then? I do not want to use an avg Aggregation. I thought that I would probably have to programmatically convert all avg functions to something like this: [Measures].[M] / count([Measure].[M]=tony or soemthing like this. not sure again.

The Avg function receives a set as a first parameter, and the measure you want to calculate the average of as a second.

The second parameter is optional, so in this case you are saying to Analysis Services: "give me the average of the measures in the current query context for the set [Measures].[M]" That is: (Measures].[M] / 1)

Since you want to calculate the avg along the time dimension, you should say:

Avg([Time],[2006].Members, [Measures].[M]).

For mor information on Avg see:

http://msdn2.microsoft.com/en-us/library/ms146067.aspx

and

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=390791&SiteID=1


aggregation functions

hi all,
it could be possible to do something like sum(other aggregation functions)?
i mean to have nested aggregation functions.
thank youAggregates of aggregates is currently not supported. This feature is on the
wish list for inclusion in a future release.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Mirela" <Mirela@.discussions.microsoft.com> wrote in message
news:39108DA6-4E27-4B6A-823D-563D354FD4AE@.microsoft.com...
> hi all,
> it could be possible to do something like sum(other aggregation
functions)?
> i mean to have nested aggregation functions.
> thank you

Thursday, March 8, 2012

aggregate functions vs. non-numeric data

RS doesn't like this expression that's supposed to total up all the debit values in my ledger:

=RunningValue( iif(Fields!Amount.Value < 1, 0, Fields!Amount.Value), Sum, Nothing)

I'm getting this error :

The value expression for the textbox ‘APTotal’ uses a numeric aggregate function on data that is not numeric. Numeric aggregate functions (Sum, Avg, StDev, Var, StDevP, and VarP) can only aggregate numeric data.

I take issue with its saying my data is not numeric. The matching field in the database is of type money.

Any thoughts on what i'm doing wrong?


Ian Pert
CMS Software, Business Integenct UnitOh, got it. Problem wasn't my Fields!Amount.Value, but simply that 0 wasn't the same datatype. Replaced 0 with Nothing, like so

=RunningValue( iif(Fields!Amount.Value < 1, Nothing, Fields!Amount.Value), Sum, Nothing)

And it worked like a charm.

Aggregate Functions Support?

Does anyone know if the jdbc driver for SQL Server
support aggregate functions such as AVG, SUM, COUNT ?
I can't find any documentation stating it does or
doesn't, but my testing seems to show that it does not.
Thanks
JD
JD wrote:

> Does anyone know if the jdbc driver for SQL Server
> support aggregate functions such as AVG, SUM, COUNT ?
> I can't find any documentation stating it does or
> doesn't, but my testing seems to show that it does not.
> Thanks
> JD
In general, the driver doesn't care about what SQL you
send to the DBMS. What problems are you having using
those functions?
Joe Weinstein at BEA
|||The result set is empty. I can successfully run the query
manually via isql.
On second thought perhaps it's an issue with the version
of java I'm running, JDK 1.2.2, that might not support
the aggregate functions.
JD
>--Original Message--
>
>JD wrote:
>
>In general, the driver doesn't care about what SQL you
>send to the DBMS. What problems are you having using
>those functions?
>Joe Weinstein at BEA
>.
>
|||anonymous@.discussions.microsoft.com wrote:

> The result set is empty. I can successfully run the query
> manually via isql.
> On second thought perhaps it's an issue with the version
> of java I'm running, JDK 1.2.2, that might not support
> the aggregate functions.
Hi. No that's not it either. If the driver doesn't care about your SQL,
the JVM certainly won't. SHow your JDBC code and function definition.
Then show what isql shows when you call it.
Joe Weinstein at BEA
[vbcol=seagreen]
> JD
|||<anonymous@.discussions.microsoft.com> schrieb im Newsbeitrag
news:2078b01c45933$f788d340$a401280a@.phx.gbl...
> The result set is empty. I can successfully run the query
> manually via isql.
> On second thought perhaps it's an issue with the version
> of java I'm running, JDK 1.2.2, that might not support
> the aggregate functions.
Nope. I'd guess that it's rather a database connection thing: do you
connect to the same database via JDBC and ISQL? Do you use the same
credentials?
robert
[vbcol=seagreen]
> JD

Aggregate Functions on Groups.

Hello Experts,

Currently my report is being shown like this:

Child Cards K04-EP-MS48S (4/12)X 1 3 5 2 K12-EP-MS128(0/0)-XX 1 0

I would prefer the report as

Child Cards K04-EP-MS48S (4/12)X

6

5

K12-EP-MS128(0/0)-XX 1 0

Is there any way that this is possible?

Thanks.

Lakshman.

Lakshman,

If your detail row is currently using: =Fields!FieldName.Value, you should be able to use =SUM(Fields!FieldName.Value).

Jessica

Aggregate Functions on char fields?

hi,
i wondered whether there is any way to simulate a kind of aggegate function
that summerizes char/varchar fiealds.
to make myself clear, please look at the following table t1 which has 2 int
fields:
f1 | f2
1 | 10
1 | 20
2 | 30
select f1, sum(f2) s1 from t1 group by f1
the result would be:
f1 | s1
1 | 30
2 | 30
so far so good.
now, please look at the following table t2 which as 1 int field and 1 char
field:
f1 | f2
1 | A
1 | B
2 | C
select f1, sum(f2) s1 from t2 group by f1
i want the result to be:
f1 | s1
1 | A,B
2 | C
is there any way to do it through 1 query only?
thanks!
edo
First of all it has nothing to do with aggregates. It is called a
contacenation
Second, I'd strongly recommend you doing such reports on the client side
create table w
(
id int,
t varchar(50) not null
)
insert into w values (1,'abc')
insert into w values (1,'def')
insert into w values (1,'ghi')
insert into w values (2,'ABC')
insert into w values (2,'DEF')
select * from w
create function dbo.fn_my ( @.id int)
returns varchar(100)
as
begin
declare @.w varchar(100)
set @.w=''
select @.w=@.w+t+',' from w where id=@.id
return @.w
end
select id,
dbo.fn_my (dd.id)
from
(
select distinct id from w
)
as dd
drop function dbo.fn_my
"edo" <ewilde@.nana.co.il> wrote in message
news:uHe0RT1lFHA.3316@.TK2MSFTNGP14.phx.gbl...
> hi,
> i wondered whether there is any way to simulate a kind of aggegate
> function
> that summerizes char/varchar fiealds.
> to make myself clear, please look at the following table t1 which has 2
> int
> fields:
> f1 | f2
> --
> 1 | 10
> 1 | 20
> 2 | 30
> select f1, sum(f2) s1 from t1 group by f1
> the result would be:
> f1 | s1
> --
> 1 | 30
> 2 | 30
> so far so good.
> now, please look at the following table t2 which as 1 int field and 1 char
> field:
> f1 | f2
> --
> 1 | A
> 1 | B
> 2 | C
> select f1, sum(f2) s1 from t2 group by f1
> i want the result to be:
> f1 | s1
> --
> 1 | A,B
> 2 | C
>
> is there any way to do it through 1 query only?
>
> thanks!
>
|||Thanks !!

Aggregate Functions on char fields?

hi,
i wondered whether there is any way to simulate a kind of aggegate function
that summerizes char/varchar fiealds.
to make myself clear, please look at the following table t1 which has 2 int
fields:
f1 | f2
--
1 | 10
1 | 20
2 | 30
select f1, sum(f2) s1 from t1 group by f1
the result would be:
f1 | s1
--
1 | 30
2 | 30
so far so good.
now, please look at the following table t2 which as 1 int field and 1 char
field:
f1 | f2
--
1 | A
1 | B
2 | C
select f1, sum(f2) s1 from t2 group by f1
i want the result to be:
f1 | s1
--
1 | A,B
2 | C
is there any way to do it through 1 query only?
thanks!edo
First of all it has nothing to do with aggregates. It is called a
contacenation
Second, I'd strongly recommend you doing such reports on the client side
create table w
(
id int,
t varchar(50) not null
)
insert into w values (1,'abc')
insert into w values (1,'def')
insert into w values (1,'ghi')
insert into w values (2,'ABC')
insert into w values (2,'DEF')
select * from w
create function dbo.fn_my ( @.id int)
returns varchar(100)
as
begin
declare @.w varchar(100)
set @.w=''
select @.w=@.w+t+',' from w where id=@.id
return @.w
end
select id,
dbo.fn_my (dd.id)
from
(
select distinct id from w
)
as dd
drop function dbo.fn_my
"edo" <ewilde@.nana.co.il> wrote in message
news:uHe0RT1lFHA.3316@.TK2MSFTNGP14.phx.gbl...
> hi,
> i wondered whether there is any way to simulate a kind of aggegate
> function
> that summerizes char/varchar fiealds.
> to make myself clear, please look at the following table t1 which has 2
> int
> fields:
> f1 | f2
> --
> 1 | 10
> 1 | 20
> 2 | 30
> select f1, sum(f2) s1 from t1 group by f1
> the result would be:
> f1 | s1
> --
> 1 | 30
> 2 | 30
> so far so good.
> now, please look at the following table t2 which as 1 int field and 1 char
> field:
> f1 | f2
> --
> 1 | A
> 1 | B
> 2 | C
> select f1, sum(f2) s1 from t2 group by f1
> i want the result to be:
> f1 | s1
> --
> 1 | A,B
> 2 | C
>
> is there any way to do it through 1 query only?
>
> thanks!
>|||Thanks !!

Aggregate Functions on char fields?

hi,
i wondered whether there is any way to simulate a kind of aggegate function
that summerizes char/varchar fiealds.
to make myself clear, please look at the following table t1 which has 2 int
fields:
f1 | f2
--
1 | 10
1 | 20
2 | 30
select f1, sum(f2) s1 from t1 group by f1
the result would be:
f1 | s1
--
1 | 30
2 | 30
so far so good.
now, please look at the following table t2 which as 1 int field and 1 char
field:
f1 | f2
--
1 | A
1 | B
2 | C
select f1, sum(f2) s1 from t2 group by f1
i want the result to be:
f1 | s1
--
1 | A,B
2 | C
is there any way to do it through 1 query only?
thanks!edo
First of all it has nothing to do with aggregates. It is called a
contacenation
Second, I'd strongly recommend you doing such reports on the client side
create table w
(
id int,
t varchar(50) not null
)
insert into w values (1,'abc')
insert into w values (1,'def')
insert into w values (1,'ghi')
insert into w values (2,'ABC')
insert into w values (2,'DEF')
select * from w
create function dbo.fn_my ( @.id int)
returns varchar(100)
as
begin
declare @.w varchar(100)
set @.w=''
select @.w=@.w+t+',' from w where id=@.id
return @.w
end
select id,
dbo.fn_my (dd.id)
from
(
select distinct id from w
)
as dd
drop function dbo.fn_my
"edo" <ewilde@.nana.co.il> wrote in message
news:uHe0RT1lFHA.3316@.TK2MSFTNGP14.phx.gbl...
> hi,
> i wondered whether there is any way to simulate a kind of aggegate
> function
> that summerizes char/varchar fiealds.
> to make myself clear, please look at the following table t1 which has 2
> int
> fields:
> f1 | f2
> --
> 1 | 10
> 1 | 20
> 2 | 30
> select f1, sum(f2) s1 from t1 group by f1
> the result would be:
> f1 | s1
> --
> 1 | 30
> 2 | 30
> so far so good.
> now, please look at the following table t2 which as 1 int field and 1 char
> field:
> f1 | f2
> --
> 1 | A
> 1 | B
> 2 | C
> select f1, sum(f2) s1 from t2 group by f1
> i want the result to be:
> f1 | s1
> --
> 1 | A,B
> 2 | C
>
> is there any way to do it through 1 query only?
>
> thanks!
>|||Thanks !!

Aggregate functions not allowed in the dataset filter

Hi,

I was trying to filter a dataset based on a condition like this: Fields!SalesAmt.value <= Sum(Fields!SalesAmt.Value)*0.05. This is nothing but it filters those SalesAmt that are less than 5% of the total sales amount. However SSRS doesn't allow to use aggregate functions in the dataset and data region filter.

Is there another way to do this?

Sincerely,

--Amde

You're trying to hide the rows correct? if so then try this

=IIF(Fields!SalesAmt.value

<= Sum(Fields!SalesAmt.Value)*0.05, true,false)
true meaning that if it is true then hid the row.

Hook this into a parameter and you have a dynamically filterable

report.

-Fap

|||Sorrt about the font size.

Here it is again.

You're trying to hide the rows correct? if so then try this

=IIF(Fields!SalesAmt.value

<= Sum(Fields!SalesAmt.Value)*0.05, true,false)
true meaning that if it is true then hid the row.

Hook this into a parameter and you have a dynamically filterable

report.

-Fap

|||

Dear Fap,

That was not my question. I just want to filter the data based on the condition I specified earlier. Please read my question carefully and let me know if you have any idea.

Sincerely,

--Amde

|||Aggregates are not supported in filter expressions (as you have seen), but there are few ways that you can work around this. Here are the first two that come to mind.

1. Filter the data returned directly in the SQL query. This can make the query more complicated. See http://msdn2.microsoft.com/en-us/library/ms179270.aspx for more information on filtering rows.

2. Use a hidden report parameter that has its default value populated by a second dataset whose query just computes and returns the result of the Aggregate. Then use the hidden report parameter in the filter expression where you were using the aggregate.

Sample Query:
SELECT Sum(SalesAmt)*.05 AS AggregateResult FROM SalesTable

Filter Expression:
Fields!SalesAmt.Value <= Parameters!AggregateResult.Value

Ian|||

Hi,

What you have said make sense, but, the thing is I am using MDX query instead of T-Sql. The link that you sent to me is helpful. It would be more helpful if you can send me similar link that uses mdx query.

Sincerely,

--Amde

|||I'm not an expert using MDX, but one way to filter the data would be to create and add another calculated member to the query, and then filter based on the result of that member. For example, create another member that will calculate whether or not the the row should be included.

The new member calculation would look something like

WITH MEMBER [Measures].[Include] AS ([Measures].[SalesAmt] <= Sum([SalesData].[SetOfAllRow], [Measures].[SalesAmt])*0.05)


Make sure to add [Measures].[Include] to the SELECT set. Then you can use this field in the data region's filter expressions. The filter expression would look something like

Fields!Include.Value = True

Or, you can use the Filter function in the query to retrive only a subset of the data. Here is more information on filtering data using MDX queries.

Filter Function:
http://msdn2.microsoft.com/en-us/library/ms146037.aspx

Slicer Axes:
http://msdn2.microsoft.com/en-us/library/ms146047.aspx

Aggregate functions in multiple tables

Hi, need help in this statement here. I have three tables here, i.e. Sales, SalesItem, & SalesPmt. I want to display a grid that shows the Total Bill and Total Payment amounts.

My try is like this: SELECT SalesNo, SUM(Price*Qty) AS TotalBill, SUM(Payment) AS TotalPayment FROM ... GROUP BY...

No syntax error or whatever found, but the result of the total amounts is incorrect.

Say the data of the respective table below:

SalesItem

NoQtyPrice115.002212.00343.50

SalesPayment

NoAmount110.0025.00

But the result I get from the above query is:

TotalBillTotalPayment86.0045.00

Total Bill should be 43.00 and Total Payment should be 15.00.

Apparently the problem is due to the fact that I and querying on multiple tables. The correct total payment amount was multiplied by the number of rows of sales items (15.00 x 3), while the correct total bill amount was multiplied by the number of rows of sale payments (43.00 x 2).

So, what is the better way of writing this query?

Use table name or table alias for each table and show the tablr (or alias) in front of column names.

Your query will look like this:

SELECT a.SalesNo, SUM(a.Price*a.Qty) AS TotalBill, SUM(b.Payment) AS TotalPayment FROM SalesItem AS a INNER JOIN SalesPayment AS b ON a.SalesNo= b.SalesNo GROUP BY a.SalesNo

|||

All the column names are unique in these three tables except the foreign key, SalesNo.

There is no difference happening here... :(

I guess I have to add two more columns in the Sales table and programmatically insert/update the TotalBill & TotalPayment just to have the grid with these two information available.

Or should I, the other way round, programatically calculate them when retriving the resultset for the grid?

Which one is the better way in the sense of processing performance? I think there sure is a difference between these two methods if you are retirving thousands of records...

I bet the first method is better, you think?

|||Could you add the table which is missing from your first post and includes all your key columns?|||

Sorry for late reply, please see the following for tables and key columns:

Table - Sales
SalesNo PK

Table - SalesItem
SalesItemNo PK
SalesNo FK
ItemCode
Qty
Price

Table - SalesPayment
SalesPaymentNo PK
SalesNo FK
Amount

|||

You should use sam data along with your table too.

Here is a query to get 43 and 15. no group by.

SELECT SUM(a.Price*a.Qty) AS TotalBill, SUM(b.Amount) AS TotalPayment
FROM SalesItem AS a LEFT JOIN SalesPayment AS b ON
a.SalesNo= b.SalesNo

Aggregate functions and locking

Do aggregate functions (sum, count, min, max) inherently cause table
locks?

More concretely, would the following query typically result in a table
lock?

select sum(quantity) as total
from products

Thanks,
Scottgobwash@.gmail.com (orders@.bunchesofbooks.com) writes:

Quote:

Originally Posted by

Do aggregate functions (sum, count, min, max) inherently cause table
locks?


Not as such.

Quote:

Originally Posted by

More concretely, would the following query typically result in a table
lock?
>
select sum(quantity) as total
from products


Yes. So would "SELECT quanity FROM products". The fact there is an
aggregate has nothing to do with it. What matters is that you access
all rows.

There is one situation where the table would not be locked and that is
if there is a non-clustered index which includes quantity, not necessarily
as the first column. In that case SQL Server will scan the index instead.
I don't know exactly which locks SQL Server takes out in this case. It
appears reasonable that it would lock the index, but I am not sure.
--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se
Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/pr...oads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodin...ions/books.mspx|||Thanks for the fast response. I just threw that out as a sample query,
but if a where clause were present, what behavior should be expected?

Scott

On Nov 29, 4:50 pm, Erland Sommarskog <esq...@.sommarskog.sewrote:

Quote:

Originally Posted by

gobw...@.gmail.com (ord...@.bunchesofbooks.com) writes:

Quote:

Originally Posted by

Do aggregate functions (sum, count, min, max) inherently cause table
locks?Not as such.


>

Quote:

Originally Posted by

More concretely, would the following query typically result in a table
lock?


>

Quote:

Originally Posted by

select sum(quantity) as total
from productsYes. So would "SELECT quanity FROM products". The fact there is an


aggregate has nothing to do with it. What matters is that you access
all rows.
>
There is one situation where the table would not be locked and that is
if there is a non-clustered index which includes quantity, not necessarily
as the first column. In that case SQL Server will scan the index instead.
I don't know exactly which locks SQL Server takes out in this case. It
appears reasonable that it would lock the index, but I am not sure.
--
Erland Sommarskog, SQL Server MVP, esq...@.sommarskog.se
>
Books Online for SQL Server 2005 athttp://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books...
Books Online for SQL Server 2000 athttp://www.microsoft.com/sql/prodinfo/previousversions/books.mspx

|||Gobwash (gobwash@.gmail.com) writes:

Quote:

Originally Posted by

Thanks for the fast response. I just threw that out as a sample query,
but if a where clause were present, what behavior should be expected?


It depends on the WHERE clause. If there is an index that can be used to
seek the rows, SQL Server will take out share locks. If there is no useful
index, so that the table will be scanned, there will be a table lock.

Again, aggregate or not has nothing to do with it.

--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se
Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/pr...oads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodin...ions/books.mspx

Aggregate Functions - and no records

Is the following statement documented/supported?
I can't find it documented in BOL the results for Aggregate functions when
there is no input data.
If a Aggregate function gets 0 records input, it returns null.
eg.
SELECT
MAX( Field ) AS ReturnsNull
FROM
(
SELECT TOP 0 1 AS Field
) NoRecordsRebecca York (rebecca.york {at} 2ndbyte.com) writes:
> Is the following statement documented/supported?
> I can't find it documented in BOL the results for Aggregate functions when
> there is no input data.
>
> If a Aggregate function gets 0 records input, it returns null.
> eg.
> SELECT
> MAX( Field ) AS ReturnsNull
> FROM
> (
> SELECT TOP 0 1 AS Field
> ) NoRecords
It is actually in Books Online, but it was not too easy to find it. Try
Accessing and Changing Relational Data
Query Fundamentals
Advanded Query Concepts
Using Aggregate Functions
Null Values
Here is says:
If no rows meet the condition(s) specified in the WHERE clause, COUNT
returns a value of zero. The other functions all return NULL. COUNT(*),
counts each row, even if all column values are NULL.
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se
Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.asp|||Phew :)
"Erland Sommarskog" <esquel@.sommarskog.se> wrote in message
news:Xns96F6808DFCEA4Yazorman@.127.0.0.1...
> Rebecca York (rebecca.york {at} 2ndbyte.com) writes:
when
> It is actually in Books Online, but it was not too easy to find it. Try
> Accessing and Changing Relational Data
> Query Fundamentals
> Advanded Query Concepts
> Using Aggregate Functions
> Null Values
> Here is says:
> If no rows meet the condition(s) specified in the WHERE clause, COUNT
> returns a value of zero. The other functions all return NULL. COUNT(*),
> counts each row, even if all column values are NULL.

Aggregate functions

Hi all,
Is there any way to create my own aggregate functions on SQl server 2000 ?
I know that PostgreSQL have a CREATE AGGREGATE for that matter. Is there
any aquivalent for SQL server ?
Thanx in advance for your replies.
No, though there may be a way in SQL Server 2005. What aggregate do you
need? Some aggregates that aren't built in can still be implemented in
the current version.
Steve Kass
Drew University
imparfait wrote:

>Hi all,
>Is there any way to create my own aggregate functions on SQl server 2000 ?
>I know that PostgreSQL have a CREATE AGGREGATE for that matter. Is there
>any aquivalent for SQL server ?
>
>Thanx in advance for your replies.
>
>
>
|||Hi Steve,
Thank you for ur reply.
I was surprized by the poorness of aggregation function number ( about a
dozen ).
My aim is to return for example the concatenation of some field on the
grouped by set.
here's a simplified details example:
ID | NAME
1 | foo1
2 | foo1
3 | foo2
4 | foo2
and I want to return the concatenantion of the IDs having the same NAME
something like :
select my_own_aggregation_function(ID,','), NAME from my_table group by NAME
would return :
1,2 | foo1
3,4 | foo2
the second argument of my_own_aggregation_function is a separator ( in this
example it's a "," )
Of course I can solve this another way but creating my own aggregation
function seems to me the most evident thing to think about as it avoids to
make an additional query.
Note : I am working on a huge database ( millions of lines...)
Thanx again for your answer.
"Steve Kass" <skass@.drew.edu> a crit dans le message de
news:eML4JizWEHA.808@.tk2msftngp13.phx.gbl...[vbcol=seagreen]
> No, though there may be a way in SQL Server 2005. What aggregate do you
> need? Some aggregates that aren't built in can still be implemented in
> the current version.
> Steve Kass
> Drew University
> imparfait wrote:
?
>
|||There is no feature of SQL Server specifically for this requirement,
though user-defined aggregates may be available in SQL Server 2005. It
might be well worth looking at a third-party tool such as the one at
http://www.rac4sql.net, or checking the capabilities of report writers.
Nonetheless, there are some SQL options, and here are three. They
assume that the items to be aggregated are distinct, and they all put
those items into lists in alphanumeric order.
1. If you know the maximum number of items that will appear for a
particular NAME value, you can do this, which is very efficient if there
is an index on (NAME, ID), or perhaps even on just (NAME). [Example
uses Northwind's Orders table, and itentionally shows how it can miss
too-long lists]:
use Northwind
go
select
t.CustomerID,
max(case rnk when 1 then OrderID end) +
coalesce(','+max(case rnk when 2 then OrderID end),'') +
coalesce(','+max(case rnk when 3 then OrderID end),'') +
coalesce(','+max(case rnk when 4 then OrderID end),'') +
coalesce(','+max(case rnk when 5 then OrderID end),'') +
coalesce(','+max(case rnk when 6 then OrderID end),'') +
coalesce(','+max(case rnk when 7 then OrderID end),'') +
coalesce(','+max(case rnk when 8 then OrderID end),'') +
coalesce(','+max(case rnk when 9 then OrderID end),'') +
coalesce(','+max(case rnk when 10 then OrderID end),'') +
coalesce(','+max(case rnk when 11 then OrderID end),'')
from (
select
t1.CustomerID,
cast(t1.OrderID as char(5)) as OrderID,
count(t2.OrderID) as rnk
from Orders t1, Orders t2
where t1.CustomerID = t2.CustomerID
and t1.OrderID <= t2.OrderID
group by t1.CustomerID, t1.OrderID
) t
group by CustomerID
2. If you don't know the number of items, but there is still a useful
index, a cursor is a reasonable choice:
CREATE TABLE Result (
KeyCol char(5),
List varchar(2000)
)
DECLARE C CURSOR FAST_FORWARD FOR
SELECT CustomerID as KeyCol, rtrim(OrderID) as Tag
FROM Northwind..Orders
ORDER BY 1,2
OPEN C
BEGIN TRAN
DECLARE @.currK varchar(30), @.K varchar(30),
@.nextT varchar(80), @.T varchar(2000)
FETCH NEXT FROM C INTO @.K, @.nextT
WHILE @.@.fetch_status = 0 BEGIN
SET @.T = @.nextT
SET @.currK = @.K
FETCH NEXT FROM C INTO @.K, @.nextT
WHILE @.@.fetch_status = 0 AND @.K = @.currK BEGIN
SET @.T = @.T + ',' + @.nextT
FETCH NEXT FROM C INTO @.K, @.nextT
END
INSERT INTO Result SELECT @.currK, @.T
END
COMMIT TRAN
CLOSE C
DEALLOCATE C
SELECT * FROM Result
GO
DROP TABLE Result
3. An iterative non-cursor solution is also possible:
SET NOCOUNT ON
GO
--Create a view of the data you want to aggregate
CREATE VIEW Base as
SELECT CustomerID AS KeyCol, rtrim(OrderID) AS Tag
FROM Northwind..Orders
go
--A helpful working table
SELECT A.KeyCol, A.Tag, COUNT(B.Tag) AS TagRank
INTO Working
FROM Base A JOIN Base B
ON A.Tag >= B.Tag
AND A.KeyCol = B.KeyCol
GROUP BY A.KeyCol, A.Tag
CREATE UNIQUE CLUSTERED INDEX Working_KT ON Working(KeyCol,Tag)
--The result table, ultimately, but with no list and two helpful extra
columns
SELECT KeyCol, COUNT(Tag) AS TotalTags, CAST('' AS varchar(8000)) AS TagList
INTO KeyString
FROM Working
GROUP BY KeyCol
CREATE UNIQUE CLUSTERED INDEX KeyString_KT ON KeyString(KeyCol,TotalTags)
--Put the first item in for each key
UPDATE KeyString
SET TagList = K.TagList + W.Tag
FROM KeyString K JOIN Working W
ON K.KeyCol = W.KeyCol
AND 0 < K.TotalTags
AND 1 = W.TagRank
DECLARE @.pos int
SET @.pos = 1
--Continue to put items in where there are any left
WHILE @.@.rowcount > 0 BEGIN
SET @.pos = @.pos + 1
UPDATE KeyString
SET TagList = K.TagList + ',' + W.Tag
FROM KeyString K JOIN Working W
ON K.KeyCol = W.KeyCol
AND @.pos <= K.TotalTags
AND @.pos = W.TagRank
END
--What did we get?
SELECT * FROM KeyString
ORDER BY KeyCol
--Clean up
DROP VIEW Base
DROP TABLE Working
DROP TABLE KeyString
SK
imparfait wrote:

>Hi Steve,
>Thank you for ur reply.
>I was surprized by the poorness of aggregation function number ( about a
>dozen ).
>My aim is to return for example the concatenation of some field on the
>grouped by set.
>here's a simplified details example:
>ID | NAME
>1 | foo1
>2 | foo1
>3 | foo2
>4 | foo2
>and I want to return the concatenantion of the IDs having the same NAME
>something like :
>select my_own_aggregation_function(ID,','), NAME from my_table group by NAME
>would return :
>1,2 | foo1
>3,4 | foo2
>the second argument of my_own_aggregation_function is a separator ( in this
>example it's a "," )
>Of course I can solve this another way but creating my own aggregation
>function seems to me the most evident thing to think about as it avoids to
>make an additional query.
>Note : I am working on a huge database ( millions of lines...)
>Thanx again for your answer.
>
>"Steve Kass" <skass@.drew.edu> a crit dans le message de
>news:eML4JizWEHA.808@.tk2msftngp13.phx.gbl...
>
>?
>
>
>
|||Thank you very much for ur precise and detailed answer.
"Steve Kass" <skass@.drew.edu> a crit dans le message de
news:eH6Yxx5WEHA.2520@.TK2MSFTNGP12.phx.gbl...
> There is no feature of SQL Server specifically for this requirement,
> though user-defined aggregates may be available in SQL Server 2005.
|||impafait
You dont have to know a maximum number of items
Look at below soultion works for you
create table w
(
id int,
t varchar(50)
)
insert into w values (1,'abc')
insert into w values (1,'def')
insert into w values (1,'ghi')
insert into w values (2,'ABC')
insert into w values (2,'DEF')
select * from w
create function dbo.fn_my ( @.id int)
returns varchar(100)
as
begin
declare @.w varchar(100)
set @.w=''
select @.w=@.w+t+',' from w where id=@.id
return @.w
end
select id,
dbo.fn_my (dd.id)
from
(
select distinct id from w
)
as dd
drop function dbo.fn_my
"imparfait" <imparfait@.noway.noway> wrote in message
news:%23ZsOuM6WEHA.3640@.TK2MSFTNGP11.phx.gbl...
> Thank you very much for ur precise and detailed answer.
>
> "Steve Kass" <skass@.drew.edu> a crit dans le message de
> news:eH6Yxx5WEHA.2520@.TK2MSFTNGP12.phx.gbl...
>
|||Uri,
While this works in many situations, it's not supported or documented,
and I don't recommend using it in a production environment.
SK
Uri Dimant wrote:

>impafait
>You dont have to know a maximum number of items
>Look at below soultion works for you
>create table w
>(
> id int,
> t varchar(50)
>)
>insert into w values (1,'abc')
>insert into w values (1,'def')
>insert into w values (1,'ghi')
>insert into w values (2,'ABC')
>insert into w values (2,'DEF')
>select * from w
>
>create function dbo.fn_my ( @.id int)
>returns varchar(100)
>as
>begin
>declare @.w varchar(100)
> set @.w=''
> select @.w=@.w+t+',' from w where id=@.id
> return @.w
>end
>select id,
>dbo.fn_my (dd.id)
>from
>(
> select distinct id from w
>)
>as dd
>drop function dbo.fn_my
>"imparfait" <imparfait@.noway.noway> wrote in message
>news:%23ZsOuM6WEHA.3640@.TK2MSFTNGP11.phx.gbl...
>
>
>
|||Think it's documented in a white paper somewhere - I've lost the reference now.
Should be
declare @.w varchar(100)
select @.w=coalesce(@.w+',','') +t from w where id=@.id
return @.w
"Steve Kass" wrote:

> Uri,
> While this works in many situations, it's not supported or documented,
> and I don't recommend using it in a production environment.
> SK
> Uri Dimant wrote:
>
>
|||Nigel,
The use of variables is documented, but as far as I know, if a select
statement doesn't produce a result set, the only guarantee here is that
@.w will be assigned at least one value, and no guarantee that there will
be one assignment for every row in the table, let alone any guarantee
about the order of assignments. The only mention of this I know of is
http://support.microsoft.com/default...;en-us;287515, which
says "The correct behavior for an aggregate concatenation query is
undefined", and while it also says "In order to achieve the expected
results from an aggregate concatenation query, apply any Transact-SQL
function or expression to the columns in the SELECT list rather than in
the ORDER BY clause," I have my doubts whether that sole off-handed
remark in a relatively confusing KB article is a real indication that
Microsoft intends this technique to be reliable.
SK
Nigel Rivett wrote:
[vbcol=seagreen]
>Think it's documented in a white paper somewhere - I've lost the reference now.
>Should be
>declare @.w varchar(100)
> select @.w=coalesce(@.w+',','') +t from w where id=@.id
> return @.w
>
>"Steve Kass" wrote:
>

Aggregate functions

Hi all,
Is there any way to create my own aggregate functions on SQl server 2000 ?
I know that PostgreSQL have a CREATE AGGREGATE for that matter. Is there
any aquivalent for SQL server ?
Thanx in advance for your replies.No, though there may be a way in SQL Server 2005. What aggregate do you
need? Some aggregates that aren't built in can still be implemented in
the current version.
Steve Kass
Drew University
imparfait wrote:

>Hi all,
>Is there any way to create my own aggregate functions on SQl server 2000 ?
>I know that PostgreSQL have a CREATE AGGREGATE for that matter. Is there
>any aquivalent for SQL server ?
>
>Thanx in advance for your replies.
>
>
>|||Hi Steve,
Thank you for ur reply.
I was surprized by the poorness of aggregation function number ( about a
dozen ).
My aim is to return for example the concatenation of some field on the
grouped by set.
here's a simplified details example:
ID | NAME
1 | foo1
2 | foo1
3 | foo2
4 | foo2
and I want to return the concatenantion of the IDs having the same NAME
something like :
select my_own_aggregation_function(ID,','), NAME from my_table group by NAME
would return :
1,2 | foo1
3,4 | foo2
the second argument of my_own_aggregation_function is a separator ( in this
example it's a "," )
Of course I can solve this another way but creating my own aggregation
function seems to me the most evident thing to think about as it avoids to
make an additional query.
Note : I am working on a huge database ( millions of lines...)
Thanx again for your answer.
"Steve Kass" <skass@.drew.edu> a crit dans le message de
news:eML4JizWEHA.808@.tk2msftngp13.phx.gbl...
> No, though there may be a way in SQL Server 2005. What aggregate do you
> need? Some aggregates that aren't built in can still be implemented in
> the current version.
> Steve Kass
> Drew University
> imparfait wrote:
>
?[vbcol=seagreen]
>|||Thank you very much for ur precise and detailed answer.
"Steve Kass" <skass@.drew.edu> a crit dans le message de
news:eH6Yxx5WEHA.2520@.TK2MSFTNGP12.phx.gbl...
> There is no feature of SQL Server specifically for this requirement,
> though user-defined aggregates may be available in SQL Server 2005.|||There is no feature of SQL Server specifically for this requirement,
though user-defined aggregates may be available in SQL Server 2005. It
might be well worth looking at a third-party tool such as the one at
http://www.rac4sql.net, or checking the capabilities of report writers.
Nonetheless, there are some SQL options, and here are three. They
assume that the items to be aggregated are distinct, and they all put
those items into lists in alphanumeric order.
1. If you know the maximum number of items that will appear for a
particular NAME value, you can do this, which is very efficient if there
is an index on (NAME, ID), or perhaps even on just (NAME). [Example
uses Northwind's Orders table, and itentionally shows how it can miss
too-long lists]:
use Northwind
go
select
t.CustomerID,
max(case rnk when 1 then OrderID end) +
coalesce(','+max(case rnk when 2 then OrderID end),'') +
coalesce(','+max(case rnk when 3 then OrderID end),'') +
coalesce(','+max(case rnk when 4 then OrderID end),'') +
coalesce(','+max(case rnk when 5 then OrderID end),'') +
coalesce(','+max(case rnk when 6 then OrderID end),'') +
coalesce(','+max(case rnk when 7 then OrderID end),'') +
coalesce(','+max(case rnk when 8 then OrderID end),'') +
coalesce(','+max(case rnk when 9 then OrderID end),'') +
coalesce(','+max(case rnk when 10 then OrderID end),'') +
coalesce(','+max(case rnk when 11 then OrderID end),'')
from (
select
t1.CustomerID,
cast(t1.OrderID as char(5)) as OrderID,
count(t2.OrderID) as rnk
from Orders t1, Orders t2
where t1.CustomerID = t2.CustomerID
and t1.OrderID <= t2.OrderID
group by t1.CustomerID, t1.OrderID
) t
group by CustomerID
2. If you don't know the number of items, but there is still a useful
index, a cursor is a reasonable choice:
CREATE TABLE Result (
KeyCol char(5),
List varchar(2000)
)
DECLARE C CURSOR FAST_FORWARD FOR
SELECT CustomerID as KeyCol, rtrim(OrderID) as Tag
FROM Northwind..Orders
ORDER BY 1,2
OPEN C
BEGIN TRAN
DECLARE @.currK varchar(30), @.K varchar(30),
@.nextT varchar(80), @.T varchar(2000)
FETCH NEXT FROM C INTO @.K, @.nextT
WHILE @.@.fetch_status = 0 BEGIN
SET @.T = @.nextT
SET @.currK = @.K
FETCH NEXT FROM C INTO @.K, @.nextT
WHILE @.@.fetch_status = 0 AND @.K = @.currK BEGIN
SET @.T = @.T + ',' + @.nextT
FETCH NEXT FROM C INTO @.K, @.nextT
END
INSERT INTO Result SELECT @.currK, @.T
END
COMMIT TRAN
CLOSE C
DEALLOCATE C
SELECT * FROM Result
GO
DROP TABLE Result
3. An iterative non-cursor solution is also possible:
SET NOCOUNT ON
GO
--Create a view of the data you want to aggregate
CREATE VIEW Base as
SELECT CustomerID AS KeyCol, rtrim(OrderID) AS Tag
FROM Northwind..Orders
go
--A helpful working table
SELECT A.KeyCol, A.Tag, COUNT(B.Tag) AS TagRank
INTO Working
FROM Base A JOIN Base B
ON A.Tag >= B.Tag
AND A.KeyCol = B.KeyCol
GROUP BY A.KeyCol, A.Tag
CREATE UNIQUE CLUSTERED INDEX Working_KT ON Working(KeyCol,Tag)
--The result table, ultimately, but with no list and two helpful extra
columns
SELECT KeyCol, COUNT(Tag) AS TotalTags, CAST('' AS varchar(8000)) AS TagList
INTO KeyString
FROM Working
GROUP BY KeyCol
CREATE UNIQUE CLUSTERED INDEX KeyString_KT ON KeyString(KeyCol,TotalTags)
--Put the first item in for each key
UPDATE KeyString
SET TagList = K.TagList + W.Tag
FROM KeyString K JOIN Working W
ON K.KeyCol = W.KeyCol
AND 0 < K.TotalTags
AND 1 = W.TagRank
DECLARE @.pos int
SET @.pos = 1
--Continue to put items in where there are any left
WHILE @.@.rowcount > 0 BEGIN
SET @.pos = @.pos + 1
UPDATE KeyString
SET TagList = K.TagList + ',' + W.Tag
FROM KeyString K JOIN Working W
ON K.KeyCol = W.KeyCol
AND @.pos <= K.TotalTags
AND @.pos = W.TagRank
END
--What did we get?
SELECT * FROM KeyString
ORDER BY KeyCol
--Clean up
DROP VIEW Base
DROP TABLE Working
DROP TABLE KeyString
SK
imparfait wrote:

>Hi Steve,
>Thank you for ur reply.
>I was surprized by the poorness of aggregation function number ( about a
>dozen ).
>My aim is to return for example the concatenation of some field on the
>grouped by set.
>here's a simplified details example:
>ID | NAME
>1 | foo1
>2 | foo1
>3 | foo2
>4 | foo2
>and I want to return the concatenantion of the IDs having the same NAME
>something like :
>select my_own_aggregation_function(ID,','), NAME from my_table group by NAM
E
>would return :
>1,2 | foo1
>3,4 | foo2
>the second argument of my_own_aggregation_function is a separator ( in this
>example it's a "," )
>Of course I can solve this another way but creating my own aggregation
>function seems to me the most evident thing to think about as it avoids to
>make an additional query.
>Note : I am working on a huge database ( millions of lines...)
>Thanx again for your answer.
>
>"Steve Kass" <skass@.drew.edu> a crit dans le message de
>news:eML4JizWEHA.808@.tk2msftngp13.phx.gbl...
>
>?
>
>
>|||impafait
You dont have to know a maximum number of items
Look at below soultion works for you
create table w
(
id int,
t varchar(50)
)
insert into w values (1,'abc')
insert into w values (1,'def')
insert into w values (1,'ghi')
insert into w values (2,'ABC')
insert into w values (2,'DEF')
select * from w
create function dbo.fn_my ( @.id int)
returns varchar(100)
as
begin
declare @.w varchar(100)
set @.w=''
select @.w=@.w+t+',' from w where id=@.id
return @.w
end
select id,
dbo.fn_my (dd.id)
from
(
select distinct id from w
)
as dd
drop function dbo.fn_my
"imparfait" <imparfait@.noway.noway> wrote in message
news:%23ZsOuM6WEHA.3640@.TK2MSFTNGP11.phx.gbl...
> Thank you very much for ur precise and detailed answer.
>
> "Steve Kass" <skass@.drew.edu> a crit dans le message de
> news:eH6Yxx5WEHA.2520@.TK2MSFTNGP12.phx.gbl...
>|||Uri,
While this works in many situations, it's not supported or documented,
and I don't recommend using it in a production environment.
SK
Uri Dimant wrote:

>impafait
>You dont have to know a maximum number of items
>Look at below soultion works for you
>create table w
>(
> id int,
> t varchar(50)
> )
>insert into w values (1,'abc')
>insert into w values (1,'def')
>insert into w values (1,'ghi')
>insert into w values (2,'ABC')
>insert into w values (2,'DEF')
>select * from w
>
>create function dbo.fn_my ( @.id int)
>returns varchar(100)
>as
>begin
>declare @.w varchar(100)
> set @.w=''
> select @.w=@.w+t+',' from w where id=@.id
> return @.w
>end
>select id,
>dbo.fn_my (dd.id)
>from
>(
> select distinct id from w
> )
>as dd
>drop function dbo.fn_my
>"imparfait" <imparfait@.noway.noway> wrote in message
>news:%23ZsOuM6WEHA.3640@.TK2MSFTNGP11.phx.gbl...
>
>
>|||Think it's documented in a white paper somewhere - I've lost the reference n
ow.
Should be
declare @.w varchar(100)
select @.w=coalesce(@.w+',','') +t from w where id=@.id
return @.w
"Steve Kass" wrote:

> Uri,
> While this works in many situations, it's not supported or documented,
> and I don't recommend using it in a production environment.
> SK
> Uri Dimant wrote:
>
>|||Nigel,
The use of variables is documented, but as far as I know, if a select
statement doesn't produce a result set, the only guarantee here is that
@.w will be assigned at least one value, and no guarantee that there will
be one assignment for every row in the table, let alone any guarantee
about the order of assignments. The only mention of this I know of is
http://support.microsoft.com/defaul...b;en-us;287515, which
says "The correct behavior for an aggregate concatenation query is
undefined", and while it also says "In order to achieve the expected
results from an aggregate concatenation query, apply any Transact-SQL
function or expression to the columns in the SELECT list rather than in
the ORDER BY clause," I have my doubts whether that sole off-handed
remark in a relatively confusing KB article is a real indication that
Microsoft intends this technique to be reliable.
SK
Nigel Rivett wrote:
[vbcol=seagreen]
>Think it's documented in a white paper somewhere - I've lost the reference
now.
>Should be
>declare @.w varchar(100)
> select @.w=coalesce(@.w+',','') +t from w where id=@.id
> return @.w
>
>"Steve Kass" wrote:
>
>

Tuesday, March 6, 2012

Aggregate functions

Hi all,
Is there any way to create my own aggregate functions on SQl server 2000 ?
I know that PostgreSQL have a CREATE AGGREGATE for that matter. Is there
any aquivalent for SQL server ?
Thanx in advance for your replies.No, though there may be a way in SQL Server 2005. What aggregate do you
need? Some aggregates that aren't built in can still be implemented in
the current version.
Steve Kass
Drew University
imparfait wrote:
>Hi all,
>Is there any way to create my own aggregate functions on SQl server 2000 ?
>I know that PostgreSQL have a CREATE AGGREGATE for that matter. Is there
>any aquivalent for SQL server ?
>
>Thanx in advance for your replies.
>
>
>|||Hi Steve,
Thank you for ur reply.
I was surprized by the poorness of aggregation function number ( about a
dozen ).
My aim is to return for example the concatenation of some field on the
grouped by set.
here's a simplified details example:
ID | NAME
1 | foo1
2 | foo1
3 | foo2
4 | foo2
and I want to return the concatenantion of the IDs having the same NAME
something like :
select my_own_aggregation_function(ID,','), NAME from my_table group by NAME
would return :
1,2 | foo1
3,4 | foo2
the second argument of my_own_aggregation_function is a separator ( in this
example it's a "," )
Of course I can solve this another way but creating my own aggregation
function seems to me the most evident thing to think about as it avoids to
make an additional query.
Note : I am working on a huge database ( millions of lines...)
Thanx again for your answer.
"Steve Kass" <skass@.drew.edu> a écrit dans le message de
news:eML4JizWEHA.808@.tk2msftngp13.phx.gbl...
> No, though there may be a way in SQL Server 2005. What aggregate do you
> need? Some aggregates that aren't built in can still be implemented in
> the current version.
> Steve Kass
> Drew University
> imparfait wrote:
> >Hi all,
> >Is there any way to create my own aggregate functions on SQl server 2000
?
> >
> >I know that PostgreSQL have a CREATE AGGREGATE for that matter. Is there
> >any aquivalent for SQL server ?
> >
> >
> >Thanx in advance for your replies.
> >
> >
> >
> >
> >
>|||There is no feature of SQL Server specifically for this requirement,
though user-defined aggregates may be available in SQL Server 2005. It
might be well worth looking at a third-party tool such as the one at
http://www.rac4sql.net, or checking the capabilities of report writers.
Nonetheless, there are some SQL options, and here are three. They
assume that the items to be aggregated are distinct, and they all put
those items into lists in alphanumeric order.
1. If you know the maximum number of items that will appear for a
particular NAME value, you can do this, which is very efficient if there
is an index on (NAME, ID), or perhaps even on just (NAME). [Example
uses Northwind's Orders table, and itentionally shows how it can miss
too-long lists]:
use Northwind
go
select
t.CustomerID,
max(case rnk when 1 then OrderID end) +
coalesce(','+max(case rnk when 2 then OrderID end),'') +
coalesce(','+max(case rnk when 3 then OrderID end),'') +
coalesce(','+max(case rnk when 4 then OrderID end),'') +
coalesce(','+max(case rnk when 5 then OrderID end),'') +
coalesce(','+max(case rnk when 6 then OrderID end),'') +
coalesce(','+max(case rnk when 7 then OrderID end),'') +
coalesce(','+max(case rnk when 8 then OrderID end),'') +
coalesce(','+max(case rnk when 9 then OrderID end),'') +
coalesce(','+max(case rnk when 10 then OrderID end),'') +
coalesce(','+max(case rnk when 11 then OrderID end),'')
from (
select
t1.CustomerID,
cast(t1.OrderID as char(5)) as OrderID,
count(t2.OrderID) as rnk
from Orders t1, Orders t2
where t1.CustomerID = t2.CustomerID
and t1.OrderID <= t2.OrderID
group by t1.CustomerID, t1.OrderID
) t
group by CustomerID
2. If you don't know the number of items, but there is still a useful
index, a cursor is a reasonable choice:
CREATE TABLE Result (
KeyCol char(5),
List varchar(2000)
)
DECLARE C CURSOR FAST_FORWARD FOR
SELECT CustomerID as KeyCol, rtrim(OrderID) as Tag
FROM Northwind..Orders
ORDER BY 1,2
OPEN C
BEGIN TRAN
DECLARE @.currK varchar(30), @.K varchar(30),
@.nextT varchar(80), @.T varchar(2000)
FETCH NEXT FROM C INTO @.K, @.nextT
WHILE @.@.fetch_status = 0 BEGIN
SET @.T = @.nextT
SET @.currK = @.K
FETCH NEXT FROM C INTO @.K, @.nextT
WHILE @.@.fetch_status = 0 AND @.K = @.currK BEGIN
SET @.T = @.T + ',' + @.nextT
FETCH NEXT FROM C INTO @.K, @.nextT
END
INSERT INTO Result SELECT @.currK, @.T
END
COMMIT TRAN
CLOSE C
DEALLOCATE C
SELECT * FROM Result
GO
DROP TABLE Result
3. An iterative non-cursor solution is also possible:
SET NOCOUNT ON
GO
--Create a view of the data you want to aggregate
CREATE VIEW Base as
SELECT CustomerID AS KeyCol, rtrim(OrderID) AS Tag
FROM Northwind..Orders
go
--A helpful working table
SELECT A.KeyCol, A.Tag, COUNT(B.Tag) AS TagRank
INTO Working
FROM Base A JOIN Base B
ON A.Tag >= B.Tag
AND A.KeyCol = B.KeyCol
GROUP BY A.KeyCol, A.Tag
CREATE UNIQUE CLUSTERED INDEX Working_KT ON Working(KeyCol,Tag)
--The result table, ultimately, but with no list and two helpful extra
columns
SELECT KeyCol, COUNT(Tag) AS TotalTags, CAST('' AS varchar(8000)) AS TagList
INTO KeyString
FROM Working
GROUP BY KeyCol
CREATE UNIQUE CLUSTERED INDEX KeyString_KT ON KeyString(KeyCol,TotalTags)
--Put the first item in for each key
UPDATE KeyString
SET TagList = K.TagList + W.Tag
FROM KeyString K JOIN Working W
ON K.KeyCol = W.KeyCol
AND 0 < K.TotalTags
AND 1 = W.TagRank
DECLARE @.pos int
SET @.pos = 1
--Continue to put items in where there are any left
WHILE @.@.rowcount > 0 BEGIN
SET @.pos = @.pos + 1
UPDATE KeyString
SET TagList = K.TagList + ',' + W.Tag
FROM KeyString K JOIN Working W
ON K.KeyCol = W.KeyCol
AND @.pos <= K.TotalTags
AND @.pos = W.TagRank
END
--What did we get?
SELECT * FROM KeyString
ORDER BY KeyCol
--Clean up
DROP VIEW Base
DROP TABLE Working
DROP TABLE KeyString
SK
imparfait wrote:
>Hi Steve,
>Thank you for ur reply.
>I was surprized by the poorness of aggregation function number ( about a
>dozen ).
>My aim is to return for example the concatenation of some field on the
>grouped by set.
>here's a simplified details example:
>ID | NAME
>1 | foo1
>2 | foo1
>3 | foo2
>4 | foo2
>and I want to return the concatenantion of the IDs having the same NAME
>something like :
>select my_own_aggregation_function(ID,','), NAME from my_table group by NAME
>would return :
>1,2 | foo1
>3,4 | foo2
>the second argument of my_own_aggregation_function is a separator ( in this
>example it's a "," )
>Of course I can solve this another way but creating my own aggregation
>function seems to me the most evident thing to think about as it avoids to
>make an additional query.
>Note : I am working on a huge database ( millions of lines...)
>Thanx again for your answer.
>
>"Steve Kass" <skass@.drew.edu> a écrit dans le message de
>news:eML4JizWEHA.808@.tk2msftngp13.phx.gbl...
>
>>No, though there may be a way in SQL Server 2005. What aggregate do you
>>need? Some aggregates that aren't built in can still be implemented in
>>the current version.
>>Steve Kass
>>Drew University
>>imparfait wrote:
>>
>>Hi all,
>>Is there any way to create my own aggregate functions on SQl server 2000
>>
>?
>
>>I know that PostgreSQL have a CREATE AGGREGATE for that matter. Is there
>>any aquivalent for SQL server ?
>>
>>Thanx in advance for your replies.
>>
>>
>>
>
>|||Thank you very much for ur precise and detailed answer.
"Steve Kass" <skass@.drew.edu> a écrit dans le message de
news:eH6Yxx5WEHA.2520@.TK2MSFTNGP12.phx.gbl...
> There is no feature of SQL Server specifically for this requirement,
> though user-defined aggregates may be available in SQL Server 2005.|||impafait
You dont have to know a maximum number of items
Look at below soultion works for you
create table w
(
id int,
t varchar(50)
)
insert into w values (1,'abc')
insert into w values (1,'def')
insert into w values (1,'ghi')
insert into w values (2,'ABC')
insert into w values (2,'DEF')
select * from w
create function dbo.fn_my ( @.id int)
returns varchar(100)
as
begin
declare @.w varchar(100)
set @.w=''
select @.w=@.w+t+',' from w where id=@.id
return @.w
end
select id,
dbo.fn_my (dd.id)
from
(
select distinct id from w
)
as dd
drop function dbo.fn_my
"imparfait" <imparfait@.noway.noway> wrote in message
news:%23ZsOuM6WEHA.3640@.TK2MSFTNGP11.phx.gbl...
> Thank you very much for ur precise and detailed answer.
>
> "Steve Kass" <skass@.drew.edu> a écrit dans le message de
> news:eH6Yxx5WEHA.2520@.TK2MSFTNGP12.phx.gbl...
> > There is no feature of SQL Server specifically for this requirement,
> > though user-defined aggregates may be available in SQL Server 2005.
>|||Uri,
While this works in many situations, it's not supported or documented,
and I don't recommend using it in a production environment.
SK
Uri Dimant wrote:
>impafait
>You dont have to know a maximum number of items
>Look at below soultion works for you
>create table w
>(
> id int,
> t varchar(50)
>)
>insert into w values (1,'abc')
>insert into w values (1,'def')
>insert into w values (1,'ghi')
>insert into w values (2,'ABC')
>insert into w values (2,'DEF')
>select * from w
>
>create function dbo.fn_my ( @.id int)
>returns varchar(100)
>as
>begin
>declare @.w varchar(100)
> set @.w=''
> select @.w=@.w+t+',' from w where id=@.id
> return @.w
>end
>select id,
>dbo.fn_my (dd.id)
>from
>(
> select distinct id from w
>)
>as dd
>drop function dbo.fn_my
>"imparfait" <imparfait@.noway.noway> wrote in message
>news:%23ZsOuM6WEHA.3640@.TK2MSFTNGP11.phx.gbl...
>
>>Thank you very much for ur precise and detailed answer.
>>
>>"Steve Kass" <skass@.drew.edu> a écrit dans le message de
>>news:eH6Yxx5WEHA.2520@.TK2MSFTNGP12.phx.gbl...
>>
>>There is no feature of SQL Server specifically for this requirement,
>>though user-defined aggregates may be available in SQL Server 2005.
>>
>>
>
>|||Think it's documented in a white paper somewhere - I've lost the reference now.
Should be
declare @.w varchar(100)
select @.w=coalesce(@.w+',','') +t from w where id=@.id
return @.w
"Steve Kass" wrote:
> Uri,
> While this works in many situations, it's not supported or documented,
> and I don't recommend using it in a production environment.
> SK
> Uri Dimant wrote:
> >impafait
> >You dont have to know a maximum number of items
> >Look at below soultion works for you
> >create table w
> >(
> > id int,
> > t varchar(50)
> >)
> >
> >insert into w values (1,'abc')
> >insert into w values (1,'def')
> >insert into w values (1,'ghi')
> >insert into w values (2,'ABC')
> >insert into w values (2,'DEF')
> >select * from w
> >
> >
> >create function dbo.fn_my ( @.id int)
> >returns varchar(100)
> >as
> >begin
> >declare @.w varchar(100)
> > set @.w=''
> > select @.w=@.w+t+',' from w where id=@.id
> > return @.w
> >end
> >
> >select id,
> >dbo.fn_my (dd.id)
> >from
> >(
> > select distinct id from w
> >)
> >as dd
> >
> >drop function dbo.fn_my
> >"imparfait" <imparfait@.noway.noway> wrote in message
> >news:%23ZsOuM6WEHA.3640@.TK2MSFTNGP11.phx.gbl...
> >
> >
> >>Thank you very much for ur precise and detailed answer.
> >>
> >>
> >>"Steve Kass" <skass@.drew.edu> a écrit dans le message de
> >>news:eH6Yxx5WEHA.2520@.TK2MSFTNGP12.phx.gbl...
> >>
> >>
> >>There is no feature of SQL Server specifically for this requirement,
> >>though user-defined aggregates may be available in SQL Server 2005.
> >>
> >>
> >>
> >>
> >
> >
> >
> >
>|||Nigel,
The use of variables is documented, but as far as I know, if a select
statement doesn't produce a result set, the only guarantee here is that
@.w will be assigned at least one value, and no guarantee that there will
be one assignment for every row in the table, let alone any guarantee
about the order of assignments. The only mention of this I know of is
http://support.microsoft.com/default.aspx?scid=kb;en-us;287515, which
says "The correct behavior for an aggregate concatenation query is
undefined", and while it also says "In order to achieve the expected
results from an aggregate concatenation query, apply any Transact-SQL
function or expression to the columns in the SELECT list rather than in
the ORDER BY clause," I have my doubts whether that sole off-handed
remark in a relatively confusing KB article is a real indication that
Microsoft intends this technique to be reliable.
SK
Nigel Rivett wrote:
>Think it's documented in a white paper somewhere - I've lost the reference now.
>Should be
>declare @.w varchar(100)
> select @.w=coalesce(@.w+',','') +t from w where id=@.id
> return @.w
>
>"Steve Kass" wrote:
>
>>Uri,
>> While this works in many situations, it's not supported or documented,
>>and I don't recommend using it in a production environment.
>>SK
>>Uri Dimant wrote:
>>
>>impafait
>>You dont have to know a maximum number of items
>>Look at below soultion works for you
>>create table w
>>(
>>id int,
>>t varchar(50)
>>)
>>insert into w values (1,'abc')
>>insert into w values (1,'def')
>>insert into w values (1,'ghi')
>>insert into w values (2,'ABC')
>>insert into w values (2,'DEF')
>>select * from w
>>
>>create function dbo.fn_my ( @.id int)
>>returns varchar(100)
>>as
>>begin
>>declare @.w varchar(100)
>> set @.w=''
>> select @.w=@.w+t+',' from w where id=@.id
>> return @.w
>>end
>>select id,
>>dbo.fn_my (dd.id)
>>from
>>(
>>select distinct id from w
>>)
>>as dd
>>drop function dbo.fn_my
>>"imparfait" <imparfait@.noway.noway> wrote in message
>>news:%23ZsOuM6WEHA.3640@.TK2MSFTNGP11.phx.gbl...
>>
>>
>>Thank you very much for ur precise and detailed answer.
>>
>>"Steve Kass" <skass@.drew.edu> a écrit dans le message de
>>news:eH6Yxx5WEHA.2520@.TK2MSFTNGP12.phx.gbl...
>>
>>
>>There is no feature of SQL Server specifically for this requirement,
>>though user-defined aggregates may be available in SQL Server 2005.
>>
>>
>>
>>
>>
>>
>>

Aggregate function is missing when scripting database objects (SQL2005)

I installed the 'StringUtilities' assembly using the Microsoft clr integration sample. The functions work fine, however, when I script out all the objects in the database, the Aggregate function is not scripted and does not appear in any of the selection lists. The other functions (Scalar and Table-valued) scripted fine. I can right click on the Aggregate function and script it out by itself, I was just wondering why it doesn't appear when I script all the database objects or just the user-defined function objects. Thanks.

What do you do to script all objects?|||In SSMS I right-click the database in the object explorer. Then I choose Tasks > Generate Script. Then I click on "Select All" on each window. When I review the generated script the Aggregate function i.e. dbo.Concatenate() is missing. I have also found the same problem if I just try to script out the Functions. The aggregate function does not appear in the pick list of Functions to be scripted. However, if I check the 'Script all objects in the selected database' checkbox on the first screen then it does generate script for the Aggregate function.

Aggregate function is missing when scripting database objects (SQL2005)

I installed the 'StringUtilities' assembly using the Microsoft clr integration sample. The functions work fine, however, when I script out all the objects in the database, the Aggregate function is not scripted and does not appear in any of the selection lists. The other functions (Scalar and Table-valued) scripted fine. I can right click on the Aggregate function and script it out by itself, I was just wondering why it doesn't appear when I script all the database objects or just the user-defined function objects. Thanks.

What do you do to script all objects?|||In SSMS I right-click the database in the object explorer. Then I choose Tasks > Generate Script. Then I click on "Select All" on each window. When I review the generated script the Aggregate function i.e. dbo.Concatenate() is missing. I have also found the same problem if I just try to script out the Functions. The aggregate function does not appear in the pick list of Functions to be scripted. However, if I check the 'Script all objects in the selected database' checkbox on the first screen then it does generate script for the Aggregate function.