OdeToCode IC Logo

GROUP BY and Column Aliases

Monday, April 18, 2005 by scott

Here is a subtle bug you can introduce into a query. Let’s pretend we are tracking coffee sales.

CREATE TABLE CoffeeSales

(

    TransactionID int IDENTITY PRIMARY KEY,

    Customer varchar(10) NOT NULL,

    CoffeeType varchar(10) NOT NULL,

    TransactionDate datetime NOT NULL,

    Cost money NOT NULL

)

 

INSERT INTO CoffeeSales

   VALUES('Joe', 'Decaf', '2004-04-17 07:30:00', 2.25)

INSERT INTO CoffeeSales

   VALUES('Joe', 'Decaf', '2004-04-17 09:00:00', 3.25)

INSERT INTO CoffeeSales

   VALUES('Joe', 'Mocha', '2004-04-17 17:00:00', 5.00)

 

INSERT INTO CoffeeSales

   VALUES('Amy', 'Maple', '2004-04-17 15:00:00', 1.25)

INSERT INTO CoffeeSales

   VALUES('Amy', 'Mocha', '2004-04-17 16:00:00', 4.75)

INSERT INTO CoffeeSales

   VALUES('Amy', 'Mocha', '2004-04-17 17:00:00', 3.50)

Here is a query attempting to total up the sales for each customer by coffee type and date.

SELECT

    Customer,

    CoffeeType,

    CONVERT(varchar(10), TransactionDate, 101) AS TransactionDate,

    SUM(Cost) AS TotalCost,

    COUNT(*) AS TotalTransactions

 

FROM

    CoffeeSales

 

GROUP BY

    Customer, CoffeeType, TransactionDate

 

ORDER BY Customer

 

Customer   CoffeeType TransactionDate TotalCost            TotalTransactions

---------- ---------- --------------- --------------------- -----------------

Amy        Maple      04/17/2004      1.2500                1

Amy        Mocha      04/17/2004      4.7500                1

Amy        Mocha      04/17/2004      3.5000                1

Joe        Decaf      04/17/2004      2.2500                1

Joe        Decaf      04/17/2004      3.2500                1

Joe        Mocha      04/17/2004      5.0000                1

We have 6 records, and when eyeballing the resultset we don’t see why Amy’s mocha purchases and Joe’s decaf purchases are not grouping up, after all, the name, coffee type, and transaction date are identical.

To realize what went wrong we have to think about how the database engine executes the query. Records are grouped before the CONVERT expression in the SELECT list executes. We think we are grouping by the converted TransactionDate field used as a column alias, but what SQL is doing is grouping on the raw TransactionDate field from the table, then executing the CONVERT and showing the field as just a date.

A working version follows.

SELECT

    Customer,

    CoffeeType,

    CONVERT(varchar(10), TransactionDate, 101) AS TransactionDate,

    SUM(Cost) AS TotalCost,

    COUNT(*) AS TotalTransactions

 

FROM

    CoffeeSales

 

GROUP BY

    Customer, CoffeeType, CONVERT(varchar(10), TransactionDate, 101)

 

ORDER BY Customer

On Tour

Monday, April 11, 2005 by scott

This week I am traveling to Toronto to speak at VSLive! I have presentations on Thursday and Friday afternoon. Toronto is a spectacular city to visit, and the conference location looks to be in a beautiful spot.

The following week I’ll be speaking at the BaltoMSDN user group meeting in Hunt Valley, MD, just outside of Baltimore. The meeting is on Wednesday, April 20th at 6:30.

In between the two, I’ll be spending some time here, and some time here.

I think I am addicted to satellite imagery.

Is there a support group?

 

Scott's Blog @ OdeToCode.com

Monday, April 4, 2005 by scott

Completely unpredictable ...

.... since 2004.

Example Code, Redux

Thursday, March 31, 2005 by scott

I’m still trying to rationalize the existence of example code. You know, the poison pills programmers copy and paste into an otherwise healthy body of software.

Sometime today, I was thinking back my first physics class, and of three key idealizations. These idealizations have helped students learn physics since the debut of Principia Mathematica in the 1680s.

The idealizations are:

  The immoveable object.
  The irresistible force.
  The frictionless surface.

Of course, nobody actually builds bridges or launches rockets using irresistible forces and frictionless surfaces, but the concepts do make the first chapters in a physics textbook easier, and we learn from them. If there are parallels to these idealizations in the sample code on MSDN, in books, and on this blog, they would be:

  The never-null parameter.
  The always-on network.
  The perfect string of user input.

We learn from them.

Indigo Notes

Wednesday, March 30, 2005 by scott

I’ve had some time to experiment, and downloaded the WinFX CTP to give Indigo a whirl. The installation onto a Virtual PC with the VS2005 February CTP went swimmingly. I thought for a first try I’d write a client for an existing web service, and since I have a few VPCs with Reporting Services installed I looked to start a conversation between the two.

I created a plain console mode application, and added a reference to the System.ServiceModel assembly. The next step was to generate proxy classes from the Reporting Services service contract (the WSDL from ReportService.asmx).

You can create proxies with the Service Model Metadata command line tool “svcutil”. Reporting Services requires an authenticated caller by default, but I did not find a way for svcutil to send my credentials. I could work around this problem by hitting the WSDL page with IE and saving a WSDL file to disk, but it turns out authentication made for more difficulties later on, so ultimately I setup Reporting Services to allow anonymous access.

The first pass with svcutil failed and told me it could not import the type ArrayOfStrings. With help from Hoop in the newsgroups, I finally got the right command line switches needed to create proxy classes.

>svcutil /out:ssrs.cs /config:app.config /tm /uxs http://reporting/reportserver/reportservice.asmx

 

 

Microsoft (R) Service Model Metadata Tool

[Microsoft(R) .NET Framework, Version 2.0.50110.20]

Copyright (C) Microsoft Corporation. All rights reserved.

 

Generating files...

C:\dev\indigo\ListReports\app.config

C:\dev\indigo\ListReports\ssrs.cs

In the above command line I’m asking svcutil to generate a config file, to generate code using typed messages (/tm) and to generate code using the XML serializer (/uxs). The generated code goes into a file I named ssrs.cs. I’ll point out the impact of these switches in a moment, but it is interesting to note that the tool refers to the XML serializer as The Xml Serializer, so use caution, we may not realize the power we are wielding with these new tools.

The tool generates a file with all of the data contracts and service contracts, and with a proxy class to instantiate and invoke the service methods. An example of a data contract is the complex type CatalogItem (excerpted below), which represents an item (report, data source, folder) in the Report Server catalog.

[System.SerializableAttribute()]

[System.Xml.Serialization.XmlTypeAttribute(

  Namespace="http://schemas.microsoft.com/.../reportingservices")]

public partial class CatalogItem

{

    // ...  

 

    private string nameField;

 

    ///

    public string Name

    {

        get

        {

            return this.nameField;

        }

        set

        {

            this.nameField = value;

        }

    }

 

    // ...

}

Since we requested svcutil to use The XML Serializer we have serialization attributes decorating the classes instead of the DataContract attributes mentioned by Clemens Vasters. It is nice to see the generated code using private backing fields and exposing public properties - this approach does simplify serialization and data binding and is something the current tools do not give us. To mark the class as partial is also a nice touch and allows for easy extensibility without forcing inheritance.

There is also the service contract itself in the generated code, excerpted below.

[

  System.ServiceModel.ServiceContractAttribute(

    Namespace="http://schemas.microsoft.com/.../reportingservices",

    FormatMode=System.ServiceModel.ContractFormatMode.XmlSerializer)

]

public interface ReportingServiceSoap

{

    // ...   

 

    [System.ServiceModel.OperationContractAttribute(

      Action="http://schemas.microsoft.com/.../ListChildren",

      ReplyAction="http://schemas.microsoft.com/.../ListChildren")]

 

    ListChildren_ResponseMessage ListChildren(ListChildren_RequestMessage request);

 

    // ...

}

The ListChildren method returns an array of CatalogItem objects representing the content of a folder in the Report Server catalog. The method is documented as taking two parameters: the path of the folder to list, and a boolean to indicate if the listing should recurse through the subfolders. Since I told svcutil to generate typed messges (/tm), the tool packaged these parameters and return into ListChildren_Request and ListChildren_Response classes respectively. I’m not sure how I feel about this construct as yet, but it does make our intention to hop over the network look explicit.

The following program uses the generated goop to list all of the reports on the server.

using System;

 

namespace ListReports

{

    class Program

    {

        static void Main(string[] args)

        {

            ReportingServiceSoap ssrs;

            ssrs = new ReportingServiceSoapProxy();

 

            ListChildren_RequestMessage request;

            request = new ListChildren_RequestMessage();

            request.Item = "/";

            request.Recursive = true;

 

            ListChildren_ResponseMessage response;

            response = ssrs.ListChildren(request);

 

            foreach (CatalogItem item in response.CatalogItems)

            {

                if (item.Type == ItemTypeEnum.Report)

                {

                    Console.WriteLine(item.Path + item.Name);

                }

            }

        }

    }

}

Going back in time for a moment, the svcutil tool also generated an app.config file. One of the strengths in Indigo is the ability to defer the endpoints, transports, and protocols to configuration files and keep them out of the code. I tweaked the app.config slightly and the result looks like the following.

 

   

     

          address="http://reporting/ReportServer/ReportService.asmx"

          bindingConfiguration="ReportingServiceSoap"

          bindingSectionName="customBinding"

          configurationName="ReportingServiceSoap"

          contractType="ReportingServiceSoap">

         

              identityData=""

              identityType="None"

              isAddressPrivate="False" />

     

   

   

     

       

         

              mapAddressingHeadersToHttpHeaders="True"

              transferTimeout="00:10:00" />

         

              maxReadPoolSize="64" maxWritePoolSize="16"

              messageVersion="Soap11Addressing1" encoding="utf-8" />

       

     

   

 

An endpoint defines the network address to use, as well as the binding (how to communicate) and contract (what operations are available). Our binding specifies we will be using HTTP. It is in this area where Indigo truly feels like a technology preview, in the sense that watching a 30-second movie trailer on TV is just a preview to sitting in front of a big screen watching the full length feature. I couldn’t dig out enough details on configuration to determine what knobs are available for tweaking and tuning in this area, but it gives off an aura of being infinitely flexible, and composable.

On the surface, and from a client perspective only, the Indigo experience is not dramatically different from what we have today, and should be easy to pick up. The exception is configuration, which has a lot more to offer – all we need is better documentation to understand what is possible.

Getting underneath into the details, or developing a service, however, requires one to learn a new Indigo vocabulary. Indigo-ese, shall we say. One of the best ways to learn Indigo-ese is to listen or read as people use Indigo-ese. The following sources are chock full of Indigo-ese:

  Clemens Vasters: “A Weekend With Indigo”: Part I, Part II, Part III.
  Steve Maine: Amaze Your Friends With Duplex Contracts.
  Don Box: Service Contracts In Indigo.
  David Chappell: Introducing Indigo: An Early Look

Thought For The Day

Thursday, March 24, 2005 by scott

Taking the thoughts, ideas, and emotions we have in our brain,

and encoding them into an audible form, or a textual representation,

is a lossy compression at best…

Team $ystem

Wednesday, March 23, 2005 by scott

Don’t you just love when those brash, young h4xxorz in the newsgroups type Microsoft with a $ sign? Such a rebellious nature….

It’s interesting to watch the reaction to the obfuscated pricing announcement for VS 2005 Team System (a readable version, with opinion, is presented by Mike Gunderloy).

Is Team System expensive?

Expensive is a relative term, isn’t it?

Is CaliberRM expensive? Is Rational Rose Enterprise expensive? Is ClearCase or Perforce expensive? Have you ever priced just their yearly support contracts for an enterprise?

I don’t think the price is surprising given the above list, but I was hoping Team Foundation Server would be where Microsoft tried to make  money back. The server seems reasonably priced, but Visual Studio and MSDN subscriptions are handing out sticker shock – particularly to independent consultants who pay for subs out of their own pocket.

MSDN subscribers are accustomed to having the fully loaded IDE, but it doesn't look like this will come with an easily justifiable price anymore.