Showing posts with label aggregate. Show all posts
Showing posts with label aggregate. Show all posts

Monday, March 26, 2012

Grouping data by x-axis labels

Hey guys,

I have thousands of records in the data source(i.e. Cube), which includes datetime information. I want to aggregate and present the data on a bar chart on monthly basis. That means the interval between the dates should be one month. Assume that the dates value will be labeled on the x-axis of the bar chart.

I tried to find out the solution for many days. I will really appreciate if anybody give me some idea.

Sincerely,

Amde

Try creating a category group with two expressions, using the following grouping expressions.

=Fields!DateField.Value.Year
=Fields!DateField.Value.Month

For the label you could use something like, =Fields!DateField.Value.ToShortDateString()

You could also use two category groups, if you wanted an inner set of labels for the month and another outer set for the year.|||

Hi,

Thank youy for your feedback, however that doesn't solve my problem: here is the thing;

I created a bar chart report. The x-axis value of this chart is a timestamp(datetime) field of a dimension. Thousands of records are inserted in to this field everyday, as a result, I will have the timestamp information every second or minute. So here is the thing, If for instance, I want to present last 5 months data in the bar chart(x-axis), the chart can not accomodate all the data and it doesn't look good to present a data which occured every minute or hours. So I want to present the data on monthly basis based on the StartDate and EndDate parameters value provided by the user.

Assume the user wants to preview 5 months record from 2006-03-04 to 2006-07-04, the data should be aggregated and presented on monthly basis as shown below, instead of directly displaying all the data as they appear in the dataset.


2006-03-04 2006-04-04 2006-05-04 2006-06-04 2006-07-04

Please let me know if you need more clarification.

Sincerely,

Amde

|||Adding the category fields with the groupings mentioned above should produce the grouping structure you are looking for. When you tried it what happened that was incorrect?

The bounds provided by the StartDate and EndDate parameters can either be used in the the sql query. Or, if it can't be done there, then you can set a filter for the category group. Also, the reason there is a group expression for Year is that the data may span multiple years and I'm assuming that you don't want the data for the same month in multiple years to be aggregated together.

Here is a sample report that uses the northwind database to show the number of orders placed for each month. It contains a bar chart and two parameters, which are used in the sql query.

<?xml version="1.0" encoding="utf-8"?>
<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
<DataSources>
<DataSource Name="Northwind">
<ConnectionProperties>
<IntegratedSecurity>true</IntegratedSecurity>
<ConnectString>Data Source=localhost; Initial Catalog=Northwind</ConnectString>
<DataProvider>SQL</DataProvider>
</ConnectionProperties>
<rd:DataSourceID>40232364-d6a5-4917-bcad-13308e3a8f62</rd:DataSourceID>
</DataSource>
</DataSources>
<BottomMargin>1in</BottomMargin>
<RightMargin>1in</RightMargin>
<ReportParameters>
<ReportParameter Name="StartDate">
<DataType>DateTime</DataType>
<DefaultValue>
<Values>
<Value>7/1/1996</Value>
</Values>
</DefaultValue>
<AllowBlank>true</AllowBlank>
<Prompt>Start Date</Prompt>
</ReportParameter>
<ReportParameter Name="EndDate">
<DataType>DateTime</DataType>
<DefaultValue>
<Values>
<Value>11/30/1996</Value>
</Values>
</DefaultValue>
<AllowBlank>true</AllowBlank>
<Prompt>End Date</Prompt>
</ReportParameter>
</ReportParameters>
<rd:DrawGrid>true</rd:DrawGrid>
<InteractiveWidth>8.5in</InteractiveWidth>
<rd:SnapToGrid>true</rd:SnapToGrid>
<Body>
<ReportItems>
<Chart Name="chart1">
<Legend>
<Visible>true</Visible>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
</Style>
<Position>RightCenter</Position>
</Legend>
<Subtype>Plain</Subtype>
<Title />
<Height>5.125in</Height>
<CategoryAxis>
<Axis>
<Title />
<MajorGridLines>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
</Style>
</MajorGridLines>
<MinorGridLines>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
</Style>
</MinorGridLines>
<MajorTickMarks>Outside</MajorTickMarks>
<Min>0</Min>
<Margin>true</Margin>
<Visible>true</Visible>
</Axis>
</CategoryAxis>
<PointWidth>0</PointWidth>
<Left>0.375in</Left>
<ThreeDProperties>
<Rotation>30</Rotation>
<Inclination>30</Inclination>
<Shading>Simple</Shading>
<WallThickness>50</WallThickness>
</ThreeDProperties>
<DataSetName>Northwind</DataSetName>
<Top>0.125in</Top>
<PlotArea>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
<BackgroundColor>LightGrey</BackgroundColor>
</Style>
</PlotArea>
<ValueAxis>
<Axis>
<Title />
<MajorGridLines>
<ShowGridLines>true</ShowGridLines>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
</Style>
</MajorGridLines>
<MinorGridLines>
<Style>
<BorderStyle>
<Default>Solid</Default>
</BorderStyle>
</Style>
</MinorGridLines>
<MajorTickMarks>Outside</MajorTickMarks>
<Min>0</Min>
<Margin>true</Margin>
<Visible>true</Visible>
<Scalar>true</Scalar>
</Axis>
</ValueAxis>
<Type>Bar</Type>
<Width>6.5in</Width>
<CategoryGroupings>
<CategoryGrouping>
<DynamicCategories>
<Grouping Name="chart1_CategoryGroup1">
<GroupExpressions>
<GroupExpression>=Fields!OrderDate.Value.Year</GroupExpression>
<GroupExpression>=Fields!OrderDate.Value.Month</GroupExpression>
</GroupExpressions>
</Grouping>
<Label>=MonthName(Fields!OrderDate.Value.Month)</Label>
</DynamicCategories>
</CategoryGrouping>
</CategoryGroupings>
<Palette>Default</Palette>
<ChartData>
<ChartSeries>
<DataPoints>
<DataPoint>
<DataValues>
<DataValue>
<Value>=Count(Fields!OrderID.Value)</Value>
</DataValue>
</DataValues>
<DataLabel />
<Marker>
<Size>6pt</Size>
</Marker>
</DataPoint>
</DataPoints>
</ChartSeries>
</ChartData>
<Style>
<BackgroundColor>White</BackgroundColor>
</Style>
</Chart>
</ReportItems>
<Height>5.75in</Height>
</Body>
<rd:ReportID>6323408e-15e1-4a7f-8151-ac96e7ebf862</rd:ReportID>
<LeftMargin>1in</LeftMargin>
<DataSets>
<DataSet Name="Northwind">
<Query>
<rd:UseGenericDesigner>true</rd:UseGenericDesigner>
<CommandText>="SELECT OrderDate, OrderID FROM Orders WHERE Orders.OrderDate BETWEEN '" & Parameters!StartDate.Value & "' AND '" & Parameters!EndDate.Value & "'"</CommandText>
<DataSourceName>Northwind</DataSourceName>
</Query>
<Fields>
<Field Name="OrderDate">
<rd:TypeName>System.DateTime</rd:TypeName>
<DataField>OrderDate</DataField>
</Field>
<Field Name="OrderID">
<rd:TypeName>System.Int32</rd:TypeName>
<DataField>OrderID</DataField>
</Field>
</Fields>
</DataSet>
</DataSets>
<Width>9.375in</Width>
<InteractiveHeight>11in</InteractiveHeight>
<Language>en-US</Language>
<TopMargin>1in</TopMargin>
</Report>|||

Yes, that is correct. The assumption, group expression for year is also correct.

Thank you for your cooperation.

sql

Friday, March 23, 2012

grouping and showing concatenated varchar column?

When you group and wants to show the aggregate of a numeric column, you do
SUM() on it.
Is there a way to do this for a varchar type so that all the values are conc
atenated
and separated by a comma for example?
And it needs to be a single select statement. Is this possible?
Jiho Han
Senior Software Engineer
Infinity Info Systems
The Sales Technology Experts
Tel: 212.563.4400 x216
Fax: 212.760.0540
jhan@.infinityinfo.com
www.infinityinfo.com> Is there a way to do this for a varchar type so that all the values are
> concatenated and separated by a comma for example?
http://www.aspfaq.com/2529|||Thanks but none of those will work for me. It's a shame that SQL standard
doesn't have a aggregate function for something like this.
It's required often enough and it would probably be so simple to do.
If we can,
SELECT PRODUCTNAME, SUM(PRICE)
FROM SALESPRODUCT
GROUP BY PRODUCTNAME
why can't we have,
SELECT PRODUCTFAMILY, CONCAT(PRODUCTNAME, ',')
FROM SALESPRODUCT
GROUP BY PRODUCTFAMILY
I mean is that so hard?

> http://www.aspfaq.com/2529
>|||> Thanks but none of those will work for me.
Can you be more specific?

> I mean is that so hard?
The SQL Server team will have to answer that.
A question for you: Is it so hard to do this outside the database? The
result is being used outside of the database, isn't it?|||>> I mean is that so hard?
Unlike summation, concatenation requires some specific order of the
constituent items to form the csv list. Since any subset of rows in a table
are sets, they do not have any inherent order associated with it. So asking
the DBMS to provide you with an ordered list when no order exists, is
meaningless.
The workarounds involve using SQL a ordered resultset & then concatenting
the values. Some of them can be found at:
http://groups.google.com/group/micr...3e?dmode=source
With SQL 2005 you will have some more options in generating such lists,
though in most cases as Aaron mentioned, retrieving the resultset to the
client and formatting it there might be a better option.
Anith|||Ummm... wrong poster!
Anith|||I am programming against a third party OLE DB Provider such that:
- I cannot create a UDF - which would be easier.
- No Case statements
- No Declares nor multiple statements
Basically it needs to be a standard ANSI SQL and a single statement.
It's not hard to do it outside the db. And I've already done it in the pres
entation
layer. But it is more lines of code doing what seems to be a mundane task.

> Can you be more specific?
>
> The SQL Server team will have to answer that.
> A question for you: Is it so hard to do this outside the database?
> The result is being used outside of the database, isn't it?
>|||Thanks for the link. I've seen some of that. Unfortunately I'm still on
SQL 2000.
I don't think I understand your statement regarding concatenation requiring
a specific order. Why is that?
I said nothing about the order of the result set. In fact, even if it came
in no particular order, it would be ok.
But even if I needed them in a certain order, once I get a single recordset
that contain this concatenated column, it'd be a few lines of coding that
can sort the particular column in the recordset. vs. having to parse out
the rows to concatenate everything and sorting it.

> Unlike summation, concatenation requires some specific order of the
> constituent items to form the csv list. Since any subset of rows in a
> table are sets, they do not have any inherent order associated with
> it. So asking the DBMS to provide you with an ordered list when no
> order exists, is meaningless.
> The workarounds involve using SQL a ordered resultset & then
> concatenting
> the values. Some of them can be found at:
> http://groups.google.com/group/micr...er.programming/
> msg/2d85bf366dd9e73e?dmode=source
> With SQL 2005 you will have some more options in generating such
> lists, though in most cases as Aaron mentioned, retrieving the
> resultset to the client and formatting it there might be a better
> option.
>|||> Basically it needs to be a standard ANSI SQL and a single statement.
If you can't create a UDF then I'm afraid you're out of luck. This is like
saying you need a car, and you know that cars contain many parts, but you
want a car made of only a single part. Not going to happen.

> It's not hard to do it outside the db. And I've already done it in the
> presentation layer. But it is more lines of code doing what seems to be a
> mundane task.
Yep. Driving to work every morning is a mundane task too. Can't wait until
the producers of Star Trek reveal their patent-protected "beam-me-up"
technology. Until then, if I want to get to work, I still have to use the
old fashioned automobile.|||> I said nothing about the order of the result set. In fact, even if it
> came in no particular order, it would be ok.
> But even if I needed them in a certain order, once I get a single
> recordset that contain this concatenated column, it'd be a few lines of
> coding that can sort the particular column in the recordset. vs. having to
> parse out the rows to concatenate everything and sorting it.
I'm . There is ordering of the result, e.g. if you have:
1 aaron,bob,frank
2 tommy,frank,george
3 frank,bob,aaron
You'd want them listed alphabetically based on the first member in each set,
e.g.
1 aaron,bob,frank
3 frank,bob,aaron
2 tommy,frank,george
What I believe Anith is talking about is ordering of each "column", e.g. an
ordered concatenation would produce this slightly different set:
1 aaron,bob,frank
2 frank,george,tommy
3 aaron,bob,frank
Which cannot be guaranteed by SQL Server, and even when it does work, it
will have two side effects (which may or may not be desirable):
(a) it will create "order doesn't matter" duplicates (1 and 3 are now the
same)
(b) it will change the alphabetical ordering, now 1 or 3 could be first...sql

Grouping and Aggregate Functions in Reporting Services

Hi All,
Can I ask you something about Grouping and Aggregate Functions in
Reporting Services?
My question is, I have a grouping in a table like the following;
Group 1 - Manufacturer - TotalInvoicePerManufacturer
Group 2 - Region - TotalInvoicePerRegion
Group 3 - Distributor - TotalInvoicePerDistributor
Group 4 - RetailerType - Nothing
Detail - Retailer - Nothing
And my stored procedure gives the resultset like this;
Manufacturer - Region - Distributor - InvoiceAmount - Retailer -
RetailerType
As you can see above, since I have retailer name and type in my
resultset, even though InvoiceAmout is only for Distributor, I have a
couple of rows (as much as a distributor has) with the same
InvoiceAmount.
What I want is;
Group 1 - Manufacturer - TotalInvoicePerManufacturer
(=sum(Fields!TotalInvoice.Value) gives me here InvoiceAmount
multiplied by distributor's retailer count, but I need only sum of
distributors' Invoice amounts)
Group 2 - Region - TotalInvoicePerRegion
(=sum(Fields!TotalInvoice.Value) gives me here InvoiceAmount
multiplied by distributor's retailer count, but I need only sum of
distributors' Invoice amounts)
Group 3 - Distributor - TotalInvoicePerDistributor (If
amount is A, to see A - for this I use =Fields!TotalInvoice.Value and
it's OK)
Group 4 - RetailerType - Nothing
Detail - Retailer - Nothing
Can you help me?
Thanks a lot..Hi, or "Merhaba"
Even though I am not very clear about what you are trying to accomplish, I
would suggest you to use
matrix report.
-Put Group 1 > Group 2 > Group 3 > Group 4 in columns. Each group should
refer to its parent.
-Put TotalInvoice in to the data cell.
-At the end play with collapse/expand row features, for aggregates.
Good luck.
Regards,
Cem Demircioglu
"Sema Yuce" <sema.yuce@.eczacibasi.com.tr> wrote in message
news:9844673f.0412072205.70170fd5@.posting.google.com...
> Hi All,
> Can I ask you something about Grouping and Aggregate Functions in
> Reporting Services?
> My question is, I have a grouping in a table like the following;
> Group 1 - Manufacturer - TotalInvoicePerManufacturer
> Group 2 - Region - TotalInvoicePerRegion
> Group 3 - Distributor - TotalInvoicePerDistributor
> Group 4 - RetailerType - Nothing
> Detail - Retailer - Nothing
> And my stored procedure gives the resultset like this;
> Manufacturer - Region - Distributor - InvoiceAmount - Retailer -
> RetailerType
> As you can see above, since I have retailer name and type in my
> resultset, even though InvoiceAmout is only for Distributor, I have a
> couple of rows (as much as a distributor has) with the same
> InvoiceAmount.
> What I want is;
> Group 1 - Manufacturer - TotalInvoicePerManufacturer
> (=sum(Fields!TotalInvoice.Value) gives me here InvoiceAmount
> multiplied by distributor's retailer count, but I need only sum of
> distributors' Invoice amounts)
> Group 2 - Region - TotalInvoicePerRegion
> (=sum(Fields!TotalInvoice.Value) gives me here InvoiceAmount
> multiplied by distributor's retailer count, but I need only sum of
> distributors' Invoice amounts)
> Group 3 - Distributor - TotalInvoicePerDistributor (If
> amount is A, to see A - for this I use =Fields!TotalInvoice.Value and
> it's OK)
> Group 4 - RetailerType - Nothing
> Detail - Retailer - Nothing
> Can you help me?
> Thanks a lot..

Wednesday, March 21, 2012

GroupExpressions and Aggregate()

I'm using Aggregate() with a custom data extension implementing the IDataReaderExtension interface, to make RS use my
own calculation of subtotals for matrices and lists, and this works just fine as long as there is only one
<GroupExpression> tag within each <GroupExpressions> tag, e.g.:
<MatrixRows>
<RowGroupings>
<RowGrouping>
<DynamicRows>
<Grouping>
<GroupExpressions>
<GroupExpression>=Fields!Year.Value</GroupExpression>
</GroupExpressions>
</Grouping>
<ReportItems><Textbox><Value>=Fields!Year.Value</Value></Textbox></ReportItems>
</DynamicRows>
</RowGrouping>
<RowGrouping>
<DynamicRows>
<Grouping>
<GroupExpressions><GroupExpression>=Fields!Quarter.Value</GroupExpression></GroupExpressions>
</Grouping>
<ReportItems><Textbox><Value>=Fields!Quarter.Value</Value></Textbox></ReportItems>
</DynamicRows>
</RowGrouping>
<RowGrouping>
<DynamicRows>
<Grouping>
<GroupExpressions><GroupExpression>=Fields!Month.Value</GroupExpression></GroupExpressions>
</Grouping>
<ReportItems><Textbox><Value>=Fields!Month.Value</Value></Textbox></ReportItems>
</DynamicRows>
</RowGrouping>
</RowGroupings>
<MatrixRows>
But when I don't want to show an intermediate grouping, like Quarter in the above, but still want to group by it, the
matrix cells are blank:
<MatrixRows>
<RowGroupings>
<RowGrouping>
<DynamicRows>
<Grouping>
<GroupExpressions>
<GroupExpression>=Fields!Year.Value</GroupExpression>
</GroupExpressions>
</Grouping>
<ReportItems><Textbox><Value>=Fields!Year.Value</Value></Textbox></ReportItems>
</DynamicRows>
</RowGrouping>
<RowGrouping>
<DynamicRows>
<Grouping>
<GroupExpressions>
<GroupExpression>=Fields!Quarter.Value</GroupExpression>
<GroupExpression>=Fields!Month.Value</GroupExpression>
</GroupExpressions>
</Grouping>
<ReportItems><Textbox><Value>=Fields!Month.Value</Value></Textbox></ReportItems>
</DynamicRows>
</RowGrouping>
</RowGroupings>
<MatrixRows>
The dataset is identical, and returns the same results for IsAggregateRow etc.
Can someone please tell me what I'm doing wrong or misunderstanding?
Thanks!
--
Posted using Wimdows.net NntpNews Component -
Post Made from http://www.SqlJunkies.com/newsgroups Our newsgroup engine supports Post Alerts, Ratings, and Searching.Currently this is by design. Aggregate function only works when there is
only one group expression and it must be simple field reference.
Fang Wang (MSFT)
Microsoft SQL Server Reporting Services
This posting is provided "AS IS" with no warranties, and confers no rights.
"Olaf Ollgaard" <User@.-NOSPAM-SqlJunkies.com> wrote in message
news:O7PuZUCYEHA.3716@.TK2MSFTNGP11.phx.gbl...
> I'm using Aggregate() with a custom data extension implementing the
IDataReaderExtension interface, to make RS use my
> own calculation of subtotals for matrices and lists, and this works just
fine as long as there is only one
> <GroupExpression> tag within each <GroupExpressions> tag, e.g.:
> <MatrixRows>
> <RowGroupings>
> <RowGrouping>
> <DynamicRows>
> <Grouping>
> <GroupExpressions>
> <GroupExpression>=Fields!Year.Value</GroupExpression>
> </GroupExpressions>
> </Grouping>
>
<ReportItems><Textbox><Value>=Fields!Year.Value</Value></Textbox></ReportIte
ms>
> </DynamicRows>
> </RowGrouping>
> <RowGrouping>
> <DynamicRows>
> <Grouping>
>
<GroupExpressions><GroupExpression>=Fields!Quarter.Value</GroupExpression></
GroupExpressions>
> </Grouping>
>
<ReportItems><Textbox><Value>=Fields!Quarter.Value</Value></Textbox></Report
Items>
> </DynamicRows>
> </RowGrouping>
> <RowGrouping>
> <DynamicRows>
> <Grouping>
>
<GroupExpressions><GroupExpression>=Fields!Month.Value</GroupExpression></Gr
oupExpressions>
> </Grouping>
>
<ReportItems><Textbox><Value>=Fields!Month.Value</Value></Textbox></ReportIt
ems>
> </DynamicRows>
> </RowGrouping>
> </RowGroupings>
> <MatrixRows>
> But when I don't want to show an intermediate grouping, like Quarter in
the above, but still want to group by it, the
> matrix cells are blank:
> <MatrixRows>
> <RowGroupings>
> <RowGrouping>
> <DynamicRows>
> <Grouping>
> <GroupExpressions>
> <GroupExpression>=Fields!Year.Value</GroupExpression>
> </GroupExpressions>
> </Grouping>
>
<ReportItems><Textbox><Value>=Fields!Year.Value</Value></Textbox></ReportIte
ms>
> </DynamicRows>
> </RowGrouping>
> <RowGrouping>
> <DynamicRows>
> <Grouping>
> <GroupExpressions>
> <GroupExpression>=Fields!Quarter.Value</GroupExpression>
> <GroupExpression>=Fields!Month.Value</GroupExpression>
> </GroupExpressions>
> </Grouping>
>
<ReportItems><Textbox><Value>=Fields!Month.Value</Value></Textbox></ReportIt
ems>
> </DynamicRows>
> </RowGrouping>
> </RowGroupings>
> <MatrixRows>
> The dataset is identical, and returns the same results for IsAggregateRow
etc.
> Can someone please tell me what I'm doing wrong or misunderstanding?
> Thanks!
> --
> Posted using Wimdows.net NntpNews Component -
> Post Made from http://www.SqlJunkies.com/newsgroups Our newsgroup engine
supports Post Alerts, Ratings, and Searching.

Friday, March 9, 2012

group by qst

In the following query I want to return as a last column the aggregate max
value of the OrderInList field.
input >>
select *, max(OrderInList) as MaxOrderInList
from tbl_activities
where Center_ID = 81
and Fiscal_Year = '2006-2007'
group by *
order by OrderInList
output >>
Column 'tbl_activities.Activity_ID' is invalid in the select list because it
is not contained in either an aggregate function or the GROUP BY clause.
Can I achieve what I want by including the extra MaxOrderInList column
instead of returning an output param?
TIAalto wrote:
> In the following query I want to return as a last column the aggregate max
> value of the OrderInList field.
> input >>
> select *, max(OrderInList) as MaxOrderInList
> from tbl_activities
> where Center_ID = 81
> and Fiscal_Year = '2006-2007'
> group by *
> order by OrderInList
> output >>
> Column 'tbl_activities.Activity_ID' is invalid in the select list because
it
> is not contained in either an aggregate function or the GROUP BY clause.
> Can I achieve what I want by including the extra MaxOrderInList column
> instead of returning an output param?
> TIA
>
Don't be lazy, specify your field list and stop using SELECT *. Any
non-aggregate field that is listed in your field list must also be
included in your GROUP BY clause, like this:
SELECT col1, col2, col3, MAC(col4)
FROM table
GROUP BY col1, col2, col3
It's generally considered bad practice to use "SELECT *".|||You can't GROUP BY *, and you shouldn't use SELECT * in production code
anyway.
It's really not that hard to generate a list of the columns in the table,
however what do you expect to happen here? If you have data like this:
ActivityID OrderInList
1 1
1 2
What is your desired output?
If you group by ALL columns, then your max(OrderInList) is meaningless.
Try it:
CREATE TABLE dbo.floob
(
ActivityID INT,
OrderInList INT
);
SET NOCOUNT ON;
INSERT dbo.floob(ActivityID,OrderInList)
SELECT 1,1
UNION ALL
SELECT 1,2;
SELECT
ActivityID, OrderInList,
MAXOrderInList = MAX(OrderInList)
FROM
dbo.floob
GROUP BY
ActivityID, OrderInList;
-- maybe what you meant was:
SELECT
ActivityID,
MAXOrderInList = MAX(OrderInList)
FROM
dbo.floob
GROUP BY
ActivityID;
GO
DROP TABLE dbo.floob;
GO
Without proper DDL, sample data and desired results, I have little else to
offer, except that grouping by all columns in the table doesn't make any
sense.
http://www.aspfaq.com/5006
"alto" <altodorov@.hotmail.com> wrote in message
news:%23VHcK%23emGHA.2204@.TK2MSFTNGP03.phx.gbl...
> In the following query I want to return as a last column the aggregate max
> value of the OrderInList field.
> input >>
> select *, max(OrderInList) as MaxOrderInList
> from tbl_activities
> where Center_ID = 81
> and Fiscal_Year = '2006-2007'
> group by *
> order by OrderInList
> output >>
> Column 'tbl_activities.Activity_ID' is invalid in the select list because
> it is not contained in either an aggregate function or the GROUP BY
> clause.
> Can I achieve what I want by including the extra MaxOrderInList column
> instead of returning an output param?
> TIA
>|||Last column is to return the same value for all records, like this
ActivityID, other cols..., MaxOrderInList
1 1,... 2
1 2,... 2
And BTW, in response to Tracy I'd already tried w/ all the fields in the
goup by - it wouldn't allow me to include an aggregate column in the list.
Again I could return the max OrderInList in an output param; I'm just asking
if the alternative above is possible.
Txs!
"Aaron Bertrand [SQL Server MVP]" <ten.xoc@.dnartreb.noraa> wrote in message
news:uX8gRLfmGHA.4816@.TK2MSFTNGP03.phx.gbl...
> You can't GROUP BY *, and you shouldn't use SELECT * in production code
> anyway.
> It's really not that hard to generate a list of the columns in the table,
> however what do you expect to happen here? If you have data like this:
> ActivityID OrderInList
> 1 1
> 1 2
> What is your desired output?
> If you group by ALL columns, then your max(OrderInList) is meaningless.
> Try it:
> CREATE TABLE dbo.floob
> (
> ActivityID INT,
> OrderInList INT
> );
> SET NOCOUNT ON;
> INSERT dbo.floob(ActivityID,OrderInList)
> SELECT 1,1
> UNION ALL
> SELECT 1,2;
> SELECT
> ActivityID, OrderInList,
> MAXOrderInList = MAX(OrderInList)
> FROM
> dbo.floob
> GROUP BY
> ActivityID, OrderInList;
> -- maybe what you meant was:
> SELECT
> ActivityID,
> MAXOrderInList = MAX(OrderInList)
> FROM
> dbo.floob
> GROUP BY
> ActivityID;
> GO
> DROP TABLE dbo.floob;
> GO
>
> Without proper DDL, sample data and desired results, I have little else to
> offer, except that grouping by all columns in the table doesn't make any
> sense.
> http://www.aspfaq.com/5006
>
> "alto" <altodorov@.hotmail.com> wrote in message
> news:%23VHcK%23emGHA.2204@.TK2MSFTNGP03.phx.gbl...
>|||"alto" <altodorov@.hotmail.com> wrote in message
news:OT2ZkSfmGHA.4868@.TK2MSFTNGP04.phx.gbl...
> Last column is to return the same value for all records, like this
> ActivityID, other cols..., MaxOrderInList
> 1 1,... 2
> 1 2,... 2
> And BTW, in response to Tracy I'd already tried w/ all the fields in the
> goup by - it wouldn't allow me to include an aggregate column in the list.
What doesn't "wouldn't allow me" mean? Did you get an error message? What
was it? What code did you try?
I think you would have to do this with a correlated subquery, not group by.
For example, using the DDL and sample data I provided earlier:
SELECT
ActivityID,
OrderInList,
MaxOrderInList = (
SELECT MAX(OrderInList)
FROM dbo.floob
WHERE ActivityID = f.ActivityID
)
FROM
dbo.floob f;
A|||>> Last column is to return the same value for all records [sic], like this ..<<
Try a scalar subquery expression
SELECT a, b, c, ...
(SELECT MAX(order_in_list) FROM Foobar) AS order_in_list_max
FROM Foobar;|||I mean I tried this query
select *, max(OrderInList) as MaxOrderInList
from tbl_activities
where Center_ID = 81
and Fiscal_Year = '2006-2007'
group by Activity_ID,
Center_ID,
Category_ID,
Type_of_Activity ,
[Description] ,
Location_Activity ,
Date_Activity ,
Total_number_of_attendies ,
Purpose_activity ,
Fully_organized_by_org ,
Partial_assistance_of_org ,
BeginingDate_FY ,
Fiscal_Year ,
memo ,
IsRequest ,
ProposedGuest ,
ActivityType ,
DateStart ,
DateEnd ,
DateCreated ,
max(OrderInList)
order by OrderInList
w/ this result:
Server: Msg 144, Level 15, State 1, Line 26
Cannot use an aggregate or a subquery in an expression used for the group by
list of a GROUP BY clause.
"Aaron Bertrand [SQL Server MVP]" <ten.xoc@.dnartreb.noraa> wrote in message
news:eJsIHWfmGHA.856@.TK2MSFTNGP03.phx.gbl...
> "alto" <altodorov@.hotmail.com> wrote in message
> news:OT2ZkSfmGHA.4868@.TK2MSFTNGP04.phx.gbl...
> What doesn't "wouldn't allow me" mean? Did you get an error message?
> What was it? What code did you try?
> I think you would have to do this with a correlated subquery, not group
> by. For example, using the DDL and sample data I provided earlier:
> SELECT
> ActivityID,
> OrderInList,
> MaxOrderInList = (
> SELECT MAX(OrderInList)
> FROM dbo.floob
> WHERE ActivityID = f.ActivityID
> )
> FROM
> dbo.floob f;
>
> A
>|||Bingo, it worked:
input >>
select Activity_ID,
Center_ID,
Category_ID,
Type_of_Activity ,
[Description] ,
Location_Activity ,
Date_Activity ,
Total_number_of_attendies ,
Purpose_activity ,
Fully_organized_by_org ,
Partial_assistance_of_org ,
BeginingDate_FY ,
Fiscal_Year ,
memo ,
IsRequest ,
ProposedGuest ,
ActivityType ,
DateStart ,
DateEnd ,
DateCreated,
(select max(OrderInList) from tbl_activities where Center_ID = 81 and
Fiscal_Year = '2006-2007') as MaxOrderInList
from tbl_activities
where Center_ID = 81
and Fiscal_Year = '2006-2007'
group by Activity_ID,
Center_ID,
Category_ID,
Type_of_Activity ,
[Description] ,
Location_Activity ,
Date_Activity ,
Total_number_of_attendies ,
Purpose_activity ,
Fully_organized_by_org ,
Partial_assistance_of_org ,
BeginingDate_FY ,
Fiscal_Year ,
memo ,
IsRequest ,
ProposedGuest ,
ActivityType ,
DateStart ,
DateEnd ,
DateCreated ,
--(select max(OrderInList) from tbl_activities where Center_ID = 81 and
Fiscal_Year = '2006-2007')
OrderInList
order by OrderInList
output (see last column returned) >>
1309 81 1 NULL activite 1 emplacement 1 NULL NULL NULL NULL 2006-2007 1
1 2006-06-19 00:00:00.000 2006-06-24 00:00:00.000 2006-06-27 09:24:57.007 2
1310 81 1 NULL activite 2 emplacement 2 NULL NULL NULL NULL 2006-2007 1
4 2006-06-05 00:00:00.000 2006-06-17 00:00:00.000 2006-06-27 09:25:21.550 2
Txs!
"--CELKO--" <jcelko212@.earthlink.net> wrote in message
news:1151418422.623163.134150@.x69g2000cwx.googlegroups.com...
> Try a scalar subquery expression
> SELECT a, b, c, ...
> (SELECT MAX(order_in_list) FROM Foobar) AS order_in_list_max
> FROM Foobar;
>|||>I mean I tried this query
> select *, max(OrderInList) as MaxOrderInList
And like I said before, selecting all columns and then aggregating one of
them doesn't make sense.
A|||alto wrote:
> I mean I tried this query
> select *, max(OrderInList) as MaxOrderInList
> from tbl_activities
> where Center_ID = 81
> and Fiscal_Year = '2006-2007'
> group by Activity_ID,
> Center_ID,
> Category_ID,
> Type_of_Activity ,
> [Description] ,
> Location_Activity ,
> Date_Activity ,
> Total_number_of_attendies ,
> Purpose_activity ,
> Fully_organized_by_org ,
> Partial_assistance_of_org ,
> BeginingDate_FY ,
> Fiscal_Year ,
> memo ,
> IsRequest ,
> ProposedGuest ,
> ActivityType ,
> DateStart ,
> DateEnd ,
> DateCreated ,
> max(OrderInList)
> order by OrderInList
> w/ this result:
> Server: Msg 144, Level 15, State 1, Line 26
> Cannot use an aggregate or a subquery in an expression used for the group
by
> list of a GROUP BY clause.
>
**THINK** about what you're doing here. Your aggregate value (MAX) is
calculated by grouping together like values from the table. The value
of MAX is unknown until that grouping has been done, so HOW can you
include it in the grouping criteria?
As I said before, STOP USING SELECT *, be specific about the fields that
you want returned by the SELECT, and include those fields (excluding the
aggregate) in your GROUP BY.

Friday, February 24, 2012

GROUP BY and aggregate functions not supported with FOR XML AUTO

Hi All
I am trying to ouput the results from my query in the form of XML. The query
is like this:
SELECT a, b, COUNT(S.c ) AS x
FROM s
GROUP BY a,b
ORDER BY a,b
FOR XML AUTO, ELEMENTS
If run this, i get an error like this:
Server: Msg 6821, Level 16, State 1, Line 1
GROUP BY and aggregate functions are currently not supported with FOR XML
AUTO.
Is there any way i can do this? Thank you all in advance.MittyKom,
Try:
SELECT * FROM (SELECT TOP 100 PERCENT a, b, COUNT(c) AS x
FROM s
GROUP BY a,b
ORDER BY a,b ) AS Y
FOR XML AUTO, ELEMENTS
HTH
Jerry
"MittyKom" <MittyKom@.discussions.microsoft.com> wrote in message
news:2D6F411D-7CA3-4EEB-A05F-1FBF03FFE7E3@.microsoft.com...
> Hi All
> I am trying to ouput the results from my query in the form of XML. The
> query
> is like this:
> SELECT a, b, COUNT(S.c ) AS x
> FROM s
> GROUP BY a,b
> ORDER BY a,b
> FOR XML AUTO, ELEMENTS
>
> If run this, i get an error like this:
> Server: Msg 6821, Level 16, State 1, Line 1
> GROUP BY and aggregate functions are currently not supported with FOR XML
> AUTO.
> Is there any way i can do this? Thank you all in advance.|||SELECT a, b, x
FROM
(SELECT a, b, COUNT(S.c) AS x
FROM S
GROUP BY a, b) AS T
ORDER BY a, b
FOR XML AUTO, ELEMENTS ;
David Portas
SQL Server MVP
--

group by Aggregate

I have the following table.
id Deptid Staffid Salary
1 1 100 85000
2 1 101 75000
3 2 201 90000
3 2 202 35000
I like to find the minumim salary for each dept and its corresponding
staffid value.
Thus.. the result should be...
Deptid Salary Staffid
1 75000 101
2 35000 202
select deptid,min(salary) from test
group by deptid
will yield the correct result less the staffid. How do I capture the
staffid for the min(salary)?
create table test (id int,deptid int, staffid int,salary int)
insert into test values (1,1,100,85000)
insert into test values (2,1,101,75000)
insert into test values (3,2,201,90000)
insert into test values (3,2,202,35000)
Many thanks.
ShahriarHi
untested
SELECT * FROM Table WHERE Salary =(SELECT MIN(Salary) FROM Table T
WHERE T.Deptid =Table.Deptid AND T.id <=Table.id)
"Shahriar" <HelloShahriar@.hotmail.com> wrote in message
news:HphNf.10696$XE6.4888@.trnddc07...
> I have the following table.
> id Deptid Staffid Salary
> 1 1 100 85000
> 2 1 101 75000
> 3 2 201 90000
> 3 2 202 35000
> I like to find the minumim salary for each dept and its corresponding
> staffid value.
> Thus.. the result should be...
> Deptid Salary Staffid
> 1 75000 101
> 2 35000 202
> select deptid,min(salary) from test
> group by deptid
> will yield the correct result less the staffid. How do I capture the
> staffid for the min(salary)?
> create table test (id int,deptid int, staffid int,salary int)
> insert into test values (1,1,100,85000)
> insert into test values (2,1,101,75000)
> insert into test values (3,2,201,90000)
> insert into test values (3,2,202,35000)
>
> Many thanks.
> Shahriar
>
>|||SELECT a.DeptID,a.Salary,a.Staffid
FROM test a
INNER JOIN(
SELECT MIN(Salary),DeptID
FROM test
GROUP BY DeptID) b(Salary,DeptID) ON a.Salary=b.Salary
AND a.DeptID=b.DeptID|||Shahriar wrote:
> I have the following table.
> id Deptid Staffid Salary
> 1 1 100 85000
> 2 1 101 75000
> 3 2 201 90000
> 3 2 202 35000
> I like to find the minumim salary for each dept and its corresponding
> staffid value.
> Thus.. the result should be...
> Deptid Salary Staffid
> 1 75000 101
> 2 35000 202
> select deptid,min(salary) from test
> group by deptid
> will yield the correct result less the staffid. How do I capture the
> staffid for the min(salary)?
> create table test (id int,deptid int, staffid int,salary int)
> insert into test values (1,1,100,85000)
> insert into test values (2,1,101,75000)
> insert into test values (3,2,201,90000)
> insert into test values (3,2,202,35000)
>
> Many thanks.
> Shahriar
What are the keys? What if there is more than one person with the same
minimum salary for one department?
Try:
SELECT id, deptid, staffid, salary
FROM test AS T
WHERE salary =
(SELECT MIN(salary)
FROM test
WHERE deptid = T.deptid);
David Portas, SQL Server MVP
Whenever possible please post enough code to reproduce your problem.
Including CREATE TABLE and INSERT statements usually helps.
State what version of SQL Server you are using and specify the content
of any error messages.
SQL Server Books Online:
http://msdn2.microsoft.com/library/ms130214(en-US,SQL.90).aspx
--

Group By

I'm trying to aggregate values and grouping the results by defined periods (6
month, 12 month, 18 month, and lifetime). I'd like to do this with one pass,
but using a CASE statement did not aggregrate correctly. The results are
more like 6 months, 7-12 months, and 13-18 months, 19-lifetime. I would like
the results of the 12 month grouping to include all of the 6 month, the 18
month to include all of the 6 and 12 month grouping, etc.
/**/
CASE WHEN pd.accountingdate > 0 THEN 'LIFE'
WHEN pd.accountingdate BETWEEN '10/19/2004' AND '04/19/2007' THEN '18MONTH'
WHEN pd.accountingdate BETWEEN '04/19/2006' AND '04/19/2007' THEN '12MONTH'
WHEN pd.accountingdate BETWEEN '10/19/2006' AND '04/19/2007' THEN '06MONTH'
ELSE NULL
END
/**/
Thanks.
"Jeremy" <Jeremy@.discussions.microsoft.com> wrote in message
news:79FBE5E0-E112-406A-B406-A5D19626FA96@.microsoft.com...
> I'm trying to aggregate values and grouping the results by defined periods
> (6
> month, 12 month, 18 month, and lifetime). I'd like to do this with one
> pass,
> but using a CASE statement did not aggregrate correctly. The results are
> more like 6 months, 7-12 months, and 13-18 months, 19-lifetime. I would
> like
> the results of the 12 month grouping to include all of the 6 month, the 18
> month to include all of the 6 and 12 month grouping, etc.
>
> /**/
> CASE WHEN pd.accountingdate > 0 THEN 'LIFE'
> WHEN pd.accountingdate BETWEEN '10/19/2004' AND '04/19/2007' THEN
> '18MONTH'
> WHEN pd.accountingdate BETWEEN '04/19/2006' AND '04/19/2007' THEN
> '12MONTH'
> WHEN pd.accountingdate BETWEEN '10/19/2006' AND '04/19/2007' THEN
> '06MONTH'
> ELSE NULL
> END
In situations like this, you should post DDL, sample data, and the actual
query. A non-working snippet of a query doesn't really help anyone
understand the complete situation.
Making some assumptions, I believe your problem is related to the use of a
single column to represent different periods. The above case expression
represents what? Is it the 6 month data, the 12 month data, ...? It can't
represent more than one "attribute" - in this case, period.
The solution is to generate separate period values. This can be done in one
of two ways. Either you aggregate the periods as separate columns or you
create a situation where you join the data to be aggregated to a table
containing the periods. In the first example, you get period data as
separate columns within the result set. In the second example, you get
period data as separate rows. You decide which way you want to proceed. It
will facilitate discussion to use either Pubs or Northwind for sample data
and queries since most people have those available (and thus do not require
the posting of DDL or sample data).
|||Understood Scott, I've already considered the approach you've suggested, but
let me expand to help everyone better understand (as you recommended).
Using a case statement gives me the following from the Orders table in
Northwind:
customerid|period|orders|freight
AROUT|06MONTH|8|275.6900
AROUT|12MONTH|2|94.7100
AROUT|18MONTH|3|101.5500
BERGS|06MONTH|7|612.0700
BERGS|12MONTH|5|419.5500
BERGS|18MONTH|4|426.2300
BERGS|LIFE|2|101.6700
/* sample statement */
SELECTcustomerid,
CASEWHEN orderdate BETWEEN '11/06/1997' AND '05/06/1998' THEN '06MONTH'
WHEN orderdate BETWEEN '05/06/1997' AND '05/06/1998' THEN '12MONTH'
WHEN orderdate BETWEEN '11/06/1996' AND '05/06/1998' THEN '18MONTH'
WHEN orderdate > 0 THEN 'LIFE'
ELSE NULL
END period,
COUNT(orderid) orders,
SUM(freight) freight
FROMorders
WHEREcustomerid IN ('AROUT', 'BERGS')
GROUP BY
customerid,
CASE WHEN orderdate BETWEEN '11/06/1997' AND '05/06/1998' THEN '06MONTH'
WHEN orderdate BETWEEN '05/06/1997' AND '05/06/1998' THEN '12MONTH'
WHEN orderdate BETWEEN '11/06/1996' AND '05/06/1998' THEN '18MONTH'
WHEN orderdate > 0 THEN 'LIFE'
ELSE NULL
END
/**/
However to get the results I seek I have to make four passes:
customerid|period|orders|freight
AROUT|06MONTH|8|275.6900
AROUT|12MONTH|8|275.6900
AROUT|18MONTH|13|471.9500
AROUT|LIFE|13|471.9500
BERGS|06MONTH|7|612.0700
BERGS|12MONTH|7|612.0700
BERGS|18MONTH|16|1457.8500
BERGS|LIFE|18|1559.5200
/* sample statement */
SELECTcustomerid,
'06MONTH' period,
COUNT(orderid) orders,
SUM(freight) freight
FROMorders
WHEREcustomerid IN ('AROUT', 'BERGS')
AND orderdate BETWEEN '11/06/1997' AND '05/06/1998'
GROUP BY customerid
UNION
SELECTcustomerid,
'12MONTH' period,
COUNT(orderid) orders,
SUM(freight) freight
FROMorders
WHEREcustomerid IN ('AROUT', 'BERGS')
AND orderdate BETWEEN '11/06/1997' AND '05/06/1998'
GROUP BY customerid
UNION
SELECTcustomerid,
'18MONTH' period,
COUNT(orderid) orders,
SUM(freight) freight
FROMorders
WHEREcustomerid IN ('AROUT', 'BERGS')
AND orderdate BETWEEN '11/06/1996' AND '05/06/1998'
GROUP BY customerid
UNION
SELECTcustomerid,
'LIFE' period,
COUNT(orderid) orders,
SUM(freight) freight
FROMorders
WHEREcustomerid IN ('AROUT', 'BERGS')
AND orderdate > 0
GROUP BY customerid
ORDER BY customerid, period
/**/
The results of the first query are affected by the sequence of the
conditions in the CASE statement. And there's the rub. I'd like to have my
results in rows because I'm aggregrating at least 20 columns and 4 periods
would push it to 80 columns. Thanks for you help.
"Scott Morris" wrote:

> "Jeremy" <Jeremy@.discussions.microsoft.com> wrote in message
> news:79FBE5E0-E112-406A-B406-A5D19626FA96@.microsoft.com...
> In situations like this, you should post DDL, sample data, and the actual
> query. A non-working snippet of a query doesn't really help anyone
> understand the complete situation.
> Making some assumptions, I believe your problem is related to the use of a
> single column to represent different periods. The above case expression
> represents what? Is it the 6 month data, the 12 month data, ...? It can't
> represent more than one "attribute" - in this case, period.
> The solution is to generate separate period values. This can be done in one
> of two ways. Either you aggregate the periods as separate columns or you
> create a situation where you join the data to be aggregated to a table
> containing the periods. In the first example, you get period data as
> separate columns within the result set. In the second example, you get
> period data as separate rows. You decide which way you want to proceed. It
> will facilitate discussion to use either Pubs or Northwind for sample data
> and queries since most people have those available (and thus do not require
> the posting of DDL or sample data).
>
>
|||Understood Scott. I've already considered the approaches you've suggested,
but let me expand to help us better understand my problem as you recommended.
The CASE statement approach gives me the following results from the Orders
table in Northwind:
customerid|period|orders|freight
AROUT|06MONTH|8|275.6900
AROUT|12MONTH|2|94.7100 /* freight should = 370.40*/
AROUT|18MONTH|3|101.5500
BERGS|06MONTH|7|612.0700
BERGS|12MONTH|5|419.5500
BERGS|18MONTH|4|426.2300
BERGS|LIFE|2|101.6700
/* sample code */
SELECTcustomerid,
CASE
WHEN orderdate BETWEEN '11/06/1997' AND '05/06/1998' THEN '06MONTH'
WHEN orderdate BETWEEN '05/06/1997' AND '05/06/1998' THEN '12MONTH'
WHEN orderdate BETWEEN '11/06/1996' AND '05/06/1998' THEN '18MONTH'
WHEN orderdate > 0 THEN 'LIFE'
ELSE NULL
END period,
COUNT(orderid) orders,
SUM(freight) freight
FROMorders
WHEREcustomerid IN ('AROUT', 'BERGS')
GROUP BY
customerid,
CASE
WHEN orderdate BETWEEN '11/06/1997' AND '05/06/1998' THEN '06MONTH'
WHEN orderdate BETWEEN '05/06/1997' AND '05/06/1998' THEN '12MONTH'
WHEN orderdate BETWEEN '11/06/1996' AND '05/06/1998' THEN '18MONTH'
WHEN orderdate > 0 THEN 'LIFE'
ELSE NULL
END
/**/
However, I would like my results to read:
customerid|period|orders|freight
AROUT|06MONTH|8|275.6900
AROUT|12MONTH|10|370.4000
AROUT|18MONTH|13|471.9500
AROUT|LIFE|13|471.9500
BERGS|06MONTH|7|612.0700
BERGS|12MONTH|12|1031.6200
BERGS|18MONTH|16|1457.8500
BERGS|LIFE|18|1559.5200
/* sample code */
SELECTcustomerid,
'06MONTH' period,
COUNT(orderid) orders,
SUM(freight) freight
FROMorders
WHEREcustomerid IN ('AROUT', 'BERGS')
AND orderdate BETWEEN '11/06/1997' AND '05/06/1998'
GROUP BY customerid
UNION
SELECTcustomerid,
'12MONTH' period,
COUNT(orderid) orders,
SUM(freight) freight
FROMorders
WHEREcustomerid IN ('AROUT', 'BERGS')
AND orderdate BETWEEN '05/06/1997' AND '05/06/1998'
GROUP BY customerid
UNION
SELECTcustomerid,
'18MONTH' period,
COUNT(orderid) orders,
SUM(freight) freight
FROMorders
WHEREcustomerid IN ('AROUT', 'BERGS')
AND orderdate BETWEEN '11/06/1996' AND '05/06/1998'
GROUP BY customerid
UNION
SELECTcustomerid,
'LIFE' period,
COUNT(orderid) orders,
SUM(freight) freight
FROMorders
WHEREcustomerid IN ('AROUT', 'BERGS')
AND orderdate > 0
GROUP BY customerid
ORDER BY customerid, period
/**/
The results of the first query are affected by the sequence of the
conditions in the CASE statement. And there's the rub. I need the 18 month
period to include 6 months and 12 months. The only way I know to do that is
through multiple passes. I prefer my results to rows as I'm aggregating at
least 20 columns and if I push the results to columns with 4 different
periods, then I would expect at least 80 columns! Any help is greatly
appreciated. Thanks.
"Scott Morris" wrote:

> "Jeremy" <Jeremy@.discussions.microsoft.com> wrote in message
> news:79FBE5E0-E112-406A-B406-A5D19626FA96@.microsoft.com...
> In situations like this, you should post DDL, sample data, and the actual
> query. A non-working snippet of a query doesn't really help anyone
> understand the complete situation.
> Making some assumptions, I believe your problem is related to the use of a
> single column to represent different periods. The above case expression
> represents what? Is it the 6 month data, the 12 month data, ...? It can't
> represent more than one "attribute" - in this case, period.
> The solution is to generate separate period values. This can be done in one
> of two ways. Either you aggregate the periods as separate columns or you
> create a situation where you join the data to be aggregated to a table
> containing the periods. In the first example, you get period data as
> separate columns within the result set. In the second example, you get
> period data as separate rows. You decide which way you want to proceed. It
> will facilitate discussion to use either Pubs or Northwind for sample data
> and queries since most people have those available (and thus do not require
> the posting of DDL or sample data).
>
>
|||> The results of the first query are affected by the sequence of the
> conditions in the CASE statement. And there's the rub. I'd like to have
> my
> results in rows because I'm aggregrating at least 20 columns and 4 periods
> would push it to 80 columns. Thanks for you help.
The secret is that you need a table of periods - which you then join to your
data while aggregating. This can be done in one pass since each "raw data
row" joins once to each appropriate period. So a row for today joins to the
6 month period while a row from 10 months ago joins to both the 6 and 12
month periods (and so forth). The trick is to generate the period table -
dynamically if needed. Below is a query (that can be used as a derived
table) to do this. Obviously, the variable isn't actually required. You
could create a table-valued function to do the same thing (especially if you
needed to reuse this logic).
declare @.today datetime
set @.today = DATEDIFF(DAY, 0, CURRENT_TIMESTAMP)
select @.today, dateadd(month, -6, @.today)
union all
select @.today, dateadd(month, -12, @.today)
union all
select @.today, dateadd(month, -18, @.today)
You may need to adjust the logic depending on your definition of periods -
the last day of the month (esp Feb in and out of a leap year) is always fun
for these types of things. With the table of periods, you simply join to
the transaction table where date of transaction is between the period start
and end dates.
|||Your solution is perfect! This increases performance and keeps my DBA happy.
I'll add this technique to my bag of tricks. Thanks Scott!
"Scott Morris" wrote:

> The secret is that you need a table of periods - which you then join to your
> data while aggregating. This can be done in one pass since each "raw data
> row" joins once to each appropriate period. So a row for today joins to the
> 6 month period while a row from 10 months ago joins to both the 6 and 12
> month periods (and so forth). The trick is to generate the period table -
> dynamically if needed. Below is a query (that can be used as a derived
> table) to do this. Obviously, the variable isn't actually required. You
> could create a table-valued function to do the same thing (especially if you
> needed to reuse this logic).
> declare @.today datetime
> set @.today = DATEDIFF(DAY, 0, CURRENT_TIMESTAMP)
> select @.today, dateadd(month, -6, @.today)
> union all
> select @.today, dateadd(month, -12, @.today)
> union all
> select @.today, dateadd(month, -18, @.today)
> You may need to adjust the logic depending on your definition of periods -
> the last day of the month (esp Feb in and out of a leap year) is always fun
> for these types of things. With the table of periods, you simply join to
> the transaction table where date of transaction is between the period start
> and end dates.
>
>