2008-12-02 160 views
0

我在下面顯示的數據庫中有3個表。我想像下面顯示的鏈接一樣製作報告。我怎麼能用datagrid或datalist做到這一點?哪一個是最好的選擇?我曾試圖做一週。填充Datagrid和Sql查詢

http://img123.imageshack.us/my.php?image=61519307xx5.jpg

COMPANY:ID_COMPANY,COMPANY_NAME

PRODUCT:ID_PRODUCT,PRODUCT_NAME

PRODUCT_SALE:ID_COMPANY,ID_PRODUCT,SALE_COUNT

更新

我可以做到這一點,有你的幫助。但是現在我也有一個小問題。

當我使用樞軸書寫查詢時,產品的名稱成爲列標題。如果產品名稱的長度大於30個字符,Oracle不會將其作爲列標題接受。所以我cro了一下,讓產品名稱30個字符來解決這個問題。之後,也出現了問題。

當我把產品名稱裁剪成30個字符時,有些產品變成了同名,並且出現了「ORA-00918:列明確定義」錯誤信息。

在這種情況下可以做什麼?

+0

是否有有限數量的公司或產品? – DevelopingChris 2008-12-02 06:10:24

+0

如果你想要更多的答案,使標題更清晰一些(Datagrid,Sql,動態列) – 2008-12-02 06:24:47

回答

1

使用標準的SQL查詢(在性能方面支點很昂貴),並在您的服務器端代碼中創建一個自定義的透視函數。這裏有幾個例子。

''' <summary> 
''' Pivots columnX as new columns for the X axis (must be unique values) and the remaining columns as 
''' the Y axis. Optionally can include columns to exclude from the Y axis. 
''' </summary> 
''' <param name="dt"></param> 
''' <param name="columnX"></param> 
''' <param name="columnsToIgnore"></param> 
''' <returns>DataTable</returns> 
''' <remarks></remarks> 
Public Shared Function Pivot(ByVal dt As DataTable, ByVal columnX As String, ByVal ParamArray columnsToIgnore As String()) As DataTable 

    Dim dt2 As New DataTable() 

    If columnX = "" Then 
     columnX = dt.Columns(0).ColumnName 
    End If 

    'Add a Column at the beginning of the table 
    dt2.Columns.Add(columnX) 

    'Read all DISTINCT values from columnX Column in the provided DataTable 
    Dim columnXValues As New List(Of String)() 

    'Create the list of columns to ignore 
    Dim listColumnsToIgnore As New List(Of String)() 
    If columnsToIgnore.Length > 0 Then 
     listColumnsToIgnore.AddRange(columnsToIgnore) 
    End If 

    If Not listColumnsToIgnore.Contains(columnX) Then 
     listColumnsToIgnore.Add(columnX) 
    End If 

    ' Add the X axis columns 
    For Each dr As DataRow In dt.Rows 
     Dim columnXTemp As String = dr(columnX).ToString() 
     If Not columnXValues.Contains(columnXTemp) Then 
      columnXValues.Add(columnXTemp) 
      dt2.Columns.Add(columnXTemp) 
     Else 
      Throw New Exception("The inversion used must have unique values for column " + columnX) 
     End If 
    Next 

    'Add a row for each non-columnX of the DataTable 
    For Each dc As DataColumn In dt.Columns 
     If Not columnXValues.Contains(dc.ColumnName) AndAlso Not listColumnsToIgnore.Contains(dc.ColumnName) Then 
      Dim dr As DataRow = dt2.NewRow() 
      dr(0) = dc.ColumnName 
      dt2.Rows.Add(dr) 
     End If 
    Next 

    'Complete the datatable with the values 
    For i As Integer = 0 To dt2.Rows.Count - 1 
     For j As Integer = 1 To dt2.Columns.Count - 1 
      dt2.Rows(i)(j) = dt.Rows(j - 1)(dt2.Rows(i)(0).ToString()).ToString() 
     Next 
    Next 

    Return dt2 

End Function 

''' <summary> 
''' Can pivot any column as X, any column as Y, and any column as Z. Sort on X, sort on Y and optionally, the 
''' values at the intersection of x and y (Z axis) can be summed. 
''' </summary> 
''' <param name="dt"></param> 
''' <param name="columnX"></param> 
''' <param name="columnY"></param> 
''' <param name="columnZ"></param> 
''' <param name="nullValue"></param> 
''' <param name="sumValues"></param> 
''' <param name="xSort"></param> 
''' <param name="ySort"></param> 
''' <returns>DataTable</returns> 
''' <remarks></remarks> 
Public Shared Function Pivot(ByVal dt As DataTable, ByVal columnX As String, ByVal columnY As String, ByVal columnZ As String, _ 
    ByVal nullValue As String, ByVal sumValues As Boolean, ByVal xSort As Sort, ByVal ySort As Sort) As DataTable 

    Dim dt2 As New DataTable() 
    Dim tickList As List(Of Long) = Nothing 

    If columnX = "" Then 
     columnX = dt.Columns(0).ColumnName 
    End If 

    'Add a Column at the beginning of the table 
    dt2.Columns.Add(columnY) 

    'Read all DISTINCT values from columnX Column in the provided DataTable 
    Dim columnXValues As New List(Of String)() 
    Dim cols As Integer = 0 

    For Each dr As DataRow In dt.Rows 
     If dr(columnX).ToString.Contains("'") Then 
      dr(columnX) = dr(columnX).ToString.Replace("'", "") 
     End If 
     If Not columnXValues.Contains(dr(columnX).ToString) Then 
      'Read each row value, if it's different from others provided, 
      'add to the list of values and creates a new Column with its value. 
      columnXValues.Add(dr(columnX).ToString) 
     End If 
    Next 

    'Sort X if needed 
    If Not xSort = Sort.None Then 
     columnXValues = SortValues(columnXValues, xSort) 
    End If 

    'Add columnX 
    For Each s As String In columnXValues 
     dt2.Columns.Add(s) 
    Next 

    'Verify Y and Z Axis columns were provided 
    If columnY <> "" AndAlso columnZ <> "" Then 
     'Read DISTINCT Values for Y Axis Column 
     Dim columnYValues As New List(Of String)() 

     For Each dr As DataRow In dt.Rows 
      If dr(columnY).ToString.Contains("'") Then 
       dr(columnY) = dr(columnY).ToString.Replace("'", "") 
      End If 
      If Not columnYValues.Contains(dr(columnY).ToString()) Then 
       columnYValues.Add(dr(columnY).ToString()) 
      End If 
     Next 

     ' Now we can sort the Y axis if needed. 
     If Not ySort = Sort.None Then 
      columnYValues = SortValues(columnYValues, ySort) 
     End If 

     'Loop all Distinct ColumnY Values 
     For Each columnYValue As String In columnYValues 
      'Create a new Row 
      Dim drReturn As DataRow = dt2.NewRow() 
      drReturn(0) = columnYValue 
      Dim rows As DataRow() = dt.[Select](columnY + "='" + columnYValue + "'") 

      'Read each row to fill the DataTable 
      For Each dr As DataRow In rows 
       Dim rowColumnTitle As String = dr(columnX).ToString() 

       'Read each column to fill the DataTable 
       For Each dc As DataColumn In dt2.Columns 
        If dc.ColumnName = rowColumnTitle Then 
         'If sumValues, try to perform a Sum 
         'If sum is not possible due to value types, use the nullValue string 
         If sumValues Then 
          If IsNumeric(dr(columnZ).ToString) Then 
           drReturn(rowColumnTitle) = Val(drReturn(rowColumnTitle).ToString) + Val(dr(columnZ).ToString) 
          Else 
           drReturn(rowColumnTitle) = nullValue 
          End If 
         Else 
          drReturn(rowColumnTitle) = dr(columnZ).ToString 
         End If 
        End If 
       Next 
      Next 

      dt2.Rows.Add(drReturn) 

     Next 
    Else 
     Throw New Exception("The columns to perform inversion are not provided") 
    End If 

    'if nullValue param was provided, fill the datable with it 
    If nullValue <> "" Then 
     For Each dr As DataRow In dt2.Rows 
      For Each dc As DataColumn In dt2.Columns 
       If dr(dc.ColumnName).ToString() = "" Then 
        dr(dc.ColumnName) = nullValue 
       End If 
      Next 
     Next 
    End If 

    Return dt2 

End Function 

''' <summary> 
''' Sorts a list of strings checking to see if they are numeric or date types. 
''' </summary> 
''' <param name="list"></param> 
''' <param name="srt"></param> 
''' <returns></returns> 
''' <remarks></remarks> 
Private Shared Function SortValues(ByVal list As List(Of String), ByVal srt As Sort) As List(Of String) 

    Dim tickList As List(Of Long) = Nothing 
    Dim dblList As List(Of Double) = Nothing 

    ' Figure out how to sort columnX 
    For Each s As String In list 
     Dim colDate As Date = Nothing 
     If Date.TryParse(s, colDate) Then 
      tickList = New List(Of Long) 
      Exit For 
     End If 
    Next 

    Dim dateTicks As Long 

    If Not tickList Is Nothing Then 
     For Each s As String In list 
      dateTicks = DateTime.Parse(s).Ticks 
      If Not tickList.Contains(dateTicks) Then 
       tickList.Add(dateTicks) 
      End If 
     Next 

     If srt = Sort.DESC Then 
      tickList.Sort() 
      tickList.Reverse() 
     ElseIf srt = Sort.ASC Then 
      tickList.Sort() 
     End If 

     list.Clear() 
     For Each lng As Long In tickList 
      list.Add(New Date(lng).ToString("G")) 
     Next 
    Else 
     Dim dbl As Double = Nothing 

     For Each s As String In list 
      If IsNumeric(s) Then 
       dblList = New List(Of Double) 
      End If 
     Next 

     If Not dblList Is Nothing Then 
      'Doubles or Integers 
      For Each s As String In list 
       dbl = Val(s) 
       If Not dblList.Contains(dbl) Then 
        dblList.Add(dbl) 
       End If 
      Next 

      If srt = Sort.DESC Then 
       dblList.Sort() 
       dblList.Reverse() 
      ElseIf srt = Sort.ASC Then 
       dblList.Sort() 
      End If 

      list.Clear() 
      For Each d As Double In dblList 
       list.Add(d.ToString) 
      Next 
     Else 
      'Strings 
      If srt = Sort.DESC Then 
       list.Sort() 
       list.Reverse() 
      ElseIf srt = Sort.ASC Then 
       list.Sort() 
      End If 
     End If 

    End If 

    Return list 

End Function 
2

你正在運行什麼版本的SQL?使用PIVOT可能是一種將數據轉換爲您想要的形式的快速方法,然後您可以使用泛型DataGrid以(幾乎)「原始」形式顯示數據 - 也就是數據的呈現方式SQL服務器。然後,您可以將DataGrid更像電子表格,而不是數據庫中數據表的代表。

下面是如何使用PIVOT表示形式你以後的數據很好的入門文檔:

http://www.tsqltutorials.com/pivot.php 

當然,我認爲這可能僅是在2005年SQL提供...等等如果你運行的是舊版本,這可能沒有幫助。

更新時間:

在Oracle 10g中,你會需要的模型擴展,這不是比PIVOT在SQL但顯然Oracle 10g的一個世界不同的做事我行我素:Check this link

1

下面的工作,如果產品編號是靜態的:

<asp:gridview> 
    <columns> 
     <asp:boundfield datafield="companyname" itemstyle-headertext="" /> 
     <asp:boundfield datafield="SALE_COUNT" itemstyle-headertext='<%# FunctionToLoadurproduct(product1) %>' /> 
     <asp:boundfield datafield="SALE_COUNT" itemstyle-headertext='<%# FunctionToLoadurproduct(product1) %>' /> 

     and so on... 
    </columns> 
</gridview > 

根據您的QUER產品ID管理產品銷售y使用內嵌查詢。

1

看起來像一個交叉報告給我。您有2個選項可以解決此問題

  1. 將數據中的數據旋轉並將其綁定到數據網格。執行此操作的確切語法會因您使用的數據庫引擎而異。 Here's an example in SQL
  2. 使用報告工具,它可以基於一個簡單的連接,就像SQL報告服務,水晶報表,XtraReports等
0

使用嵌套中繼器控制。外部中繼器將重複公司,內部將重複產品。