ASP.NET DataGrid控件數據分組操作
ASP.NET DataGrid控件數據分組操作
下面的 SQL 命令選擇所有客戶在給定年份發出的所有定單。只顯示每個定單所有項目價格的總和。
- SELECT o.customerid, od.orderid, SUM(od.quantity*od.unitprice) AS price
- FROM Orders o, [Order Details] od
- WHERE Year(o.orderdate) = @TheYear AND od.orderid=o.orderid
- GROUP BY o.customerid, od.orderid
- ORDER BY o.customerid
在 T-SQL 語言中,SELECT 語句的 GROUP BY 子句提供將預定義的匯總行添加到結果集的 WITH ROLLUP 子句。當然,這樣的匯總行具有所有其他列的布局,但每一列的內容都可以進行某種程度的自定義。下面的語句闡釋如何修改上面的命令,以使其允許使用匯總行。
- DECLARE @TheYear int
- SET @TheYear = 1998
- SELECT
- CASE GROUPING(o.customerid) WHEN 0
- THEN o.customerid ELSE '(Total)' END AS MyCustomerID,
- CASE GROUPING(od.orderid) WHEN 0
- THEN od.orderid ELSE -1 END AS MyOrderID,
- SUM(od.quantity*od.unitprice) AS price
- FROM Orders o, [Order Details] od
- WHERE Year(orderdate) = @TheYear AND od.orderid=o.orderid
- GROUP BY o.customerid, od.orderid WITH ROLLUP
- ORDER BY o.customerid, price
如果您將該代碼片段復制并粘貼到 SQL 查詢分析器中,將看到如下圖所示的內容。
GROUPING 是一種 T-SQL 聚合函數,它與 ROLLUP 一起工作于 GROUP BY 子句的主體中。使用 GROUPING 運算符將使新列添加到結果集。如果該行已經由 ROLLUP 運算符添加并因此而成為匯總行,則新列中將包含值 1。否則,該列將包含值 0。使用 CASE..WHEN..END 語句可以將這個新列與分組列合并在一起。
在上面的示例中,MyCustomerID 列在所有因其進行分組而創建的行中包含 CustomerID 列的值以及字符串 “(Total)”。同樣,當該行代表小計時,MyOrderID 列包含定單 ID 和 –1。
為了對數據進行匯總,SQL Server 還提供了幾個選項,例如,WITH CUBE 運算符和 COMPUTE BY 子句。正如您所想象的那樣,盡管一個選項的功能以某種方式與另一個選項的功能相交叉,但是所有這些選項并不完全等價。特別是,WITH CUBE 針對結果集內組與子組的每個可能的組合都生成一個匯總行。而 WITH ROLLUP 按照分組列的指定順序來進行分組。最后,COMPUTE BY(SQL Server 2000 支持它的目的僅在于獲得向后兼容性)的工作方式與 WITH ROLLUP 大體相同,不同的是它返回多個結果集,而且在由查詢優化器處理時不如 ROLLUP 效率高。
ASP.NET DataGrid控件:顯示已分組數據
當綁定到 DataGrid 控件時,由 SQL 命令返回的結果集看上去如下圖所示。
示例應用程序中使用的 DataGrid 控件按如下方式進行聲明:
- < asp:DataGrid id="grid" runat="server"
- AutoGenerateColumns="false"
- AllowPaging="true" PageSize="15"
- Font-Size="xx-small"
- CellSpacing="0" CellPadding="4" GridLines="both"
- BorderStyle="solid" BorderColor="skyblue" BorderWidth="1"
- OnItemCreated="ItemCreated"
- OnPageIndexChanged="PageIndexChanged">
- < headerstyle backcolor="skyblue" font-size="9pt" font-bold="true" />
- < itemstyle backcolor="#eeeeee" />
- < pagerstyle backcolor="skyblue" font-name="webdings"
- font-size="10pt" PrevPageText="3" NextPageText="4" />
- < Columns>
- < asp:BoundColumn DataField="MyCustId" HeaderText="Customer" />
- < asp:BoundColumn DataField="MyOrderId" HeaderText="Order #" />
- < asp:BoundColumn DataField="price" HeaderText="Amount"
- DataFormatString="{0:c}">
- < itemstyle horizontalalign="right" />
- < /asp:BoundColumn>
- < /Columns>
- < /asp:DataGrid>
使用 WITH ROLLUP 運算符獲取的數據源已經包含生成有效的報告所必需的全部信息。您可能已經注意到了,該語句添加一個頂行,其中包含由所有客戶發出的全部定單的合計。在使用 WITH ROLLUP 運算符時,如果您修改了分組行的順序,則所生成行的數量和結構可能會發生顯著變化。這額外的一行是我選擇使用特定語法的結果。如果您不需要這段信息,只需在綁定之前將它從結果集刪除。或者,可以將該行移到數據集的底部。
下面顯示的代碼闡釋如何執行 rollup 語句。從文本框中讀出的參數是要考慮的年份。結果集臨時存儲在 DataSet 對象中。在這個示例應用程序中,我將在 Session 槽中緩存 DataSet 對象。在實際環境中,這應該是受重視的選擇。通常,存儲在 Session 中的任何字節都有一個位于那里的充分理由。
- private DataSet PhysicalDataRead()
- {
- String strCnn = "SERVER=localhost;DATABASE=northwind;UID=sa;";
- SqlConnection conn = new SqlConnection(strCnn);
- // Command text using WITH ROLLUP
- StringBuilder sb = new StringBuilder("");
- sb.Append("SELECT ");
- sb.Append(" CASE GROUPING(o.customerid) WHEN 0 ");
- sb.Append(" THEN o.customerid ELSE '(Total)' END AS MyCustID, ");
- sb.Append(" CASE GROUPING(od.orderid) WHEN 0 ");
- sb.Append(" THEN od.orderid ELSE -1 END AS MyOrderID, ");
- sb.Append(" SUM(od.quantity*od.unitprice) AS price ");
- sb.Append("FROM Orders o, [Order Details] od ");
- sb.Append("WHERE Year(orderdate)=@nYear AND od.orderid=o.orderid ");
- sb.Append("GROUP BY o.customerid, od.orderid WITH ROLLUP ");
- sb.Append("ORDER BY o.customerid, price");
- String strCmd = sb.ToString();
- sb = null;
- SqlCommand cmd = new SqlCommand();
- cmd.CommandText = strCmd;
- cmd.Connection = conn;
- SqlDataAdapter da = new SqlDataAdapter(strCmd, strConn);
- da.SelectCommand = cmd;
- // Set the "year" parameter
- SqlParameter p1 = new SqlParameter("@nYear", SqlDbType.Int);
- p1.Direction = ParameterDirection.Input;
- p1.Value = Convert.ToInt32(txtYear.Text);
- cmd.Parameters.Add(p1);
- DataSet ds = new DataSet();
- da.Fill(ds, "Orders");
- return ds;
- }
為了使匯總行在該網格的頁面中清楚地顯示,需要更改匯總行的樣式和布局。這可在 ItemCreated 事件處理程序中完成。設計思路是,通過檢查定單 ID 來檢測匯總行,然后修改單元格的布局和樣式。在結果集內,匯總行的特征是定單 ID 為 –1。值 –1 是來自所使用語句的任意值。
- CASE GROUPING(od.orderid) WHEN 0 THEN od.orderid ELSE -1 END AS MyOrderID
如果不針對 orderid 列使用 GROUPING 運算符,則對于匯總行來說,該列的值將為 NULL。
以上就總結了如何使用ASP.NET DataGrid控件進行數據分組操作。
【編輯推薦】