2008-12-02 158 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

使用嵌套中继器控制。外部中继器将重复公司,内部将重复产品。