DataGrid 및 SQL 쿼리를 채우십시오
문제
아래 표시된 데이터베이스에 3 개의 테이블이 있습니다. 아래에 표시된 링크와 마찬가지로 보고서를 만들고 싶습니다. Datagrid 또는 Datalist로 어떻게 할 수 있습니까? 어느 것이 최고의 선택입니까? 나는 일주일 동안 그것을 시도했다.
회사: id_company, company_name
제품: id_product, product_name
product_sale: id_company, id_product, sale_count
업데이트되었습니다 :
나는 당신의 도움으로 그것을 할 수 있습니다. 그러나 지금도 작은 문제가 있습니다.
피벗으로 쿼리를 작성하면 제품의 이름이 열 헤더가됩니다. 제품 이름의 길이가 30 문자보다 큰 경우 Oracle은 열 헤더로 허용하지 않습니다. 그래서 나는이 문제를 해결하기 위해 제품 이름을 30 문자로 만들었습니다. 그 후 문제도 발생했습니다.
제품 이름을 30 문자로 자르면 일부 제품은 동일한 이름이되고 "ORA-00918 : 열 모호하게 정의 된 열"오류 메시지가 발생했습니다.
이 경우 무엇을 할 수 있습니까?
해결책
표준 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
다른 팁
어떤 버전의 SQL을 실행하고 있습니까? Pivot을 사용하면 데이터를 원하는 양식으로 빠르게 가져 오는 방법 일 수 있으며 일반 데이터 그라이드를 사용하여 데이터를 (거의) "RAW"양식에 표시하는 것만으로도 데이터가 표시되는 방식으로 표시됩니다. SQL 서버. 그런 다음 데이터베이스에있는대로 데이터 테이블을 대표하는 것보다 Datagrid를 스프레드 시트처럼 생각할 수 있습니다.
다음은 Pivot을 사용하여 다음 양식으로 데이터를 표현하는 방법에 대한 좋은 스타터 문서입니다.
http://www.tsqltutorials.com/pivot.php
물론, 이것은 SQL 2005에서만 사용할 수 있다고 생각합니다 ... 이전 버전을 실행하는 경우 도움이되지 않을 수 있습니다.
업데이트 :
Oracle 10G에서는 모델 확장이 필요합니다. 세계 SQL의 피벗과는 다르지만 분명히 Oracle 10G는 자체 방식으로 수행합니다. 이 링크를 확인하십시오
나에게 Crosstab 보고서처럼 보입니다. 이것에 대한 두 가지 옵션이 있습니다
- 데이터베이스의 데이터를 피벗하고 데이터를 데이터 그라이드에 바인딩하십시오. 이 작업의 정확한 구문은 사용중인 데이터베이스 엔진에 따라 다릅니다. 다음은 SQL의 예입니다
- SQL보고 서비스, Crystal Reports, XtrarePorts 등과 같은 간단한 조인을 기반으로 크로스 탭을 수행 할 수있는보고 도구를 사용하십시오.
Oracle 10G에서는 모델 확장이 필요합니다. 세계 SQL의 피벗과는 다르지만 분명히 Oracle 10G는 자체 방식으로 수행합니다.
http://technology.amis.nl/blog/300/pivoting-in-sql-using-the-10g-model-clause
제품 번호가 정적 인 경우 다음은 작동합니다.
<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 >
인라인 쿼리를 사용하여 쿼리의 제품 ID에 따라 제품 판매를 관리하십시오.
중첩 리피터 컨트롤을 사용하십시오. 외부 리피터는 회사를 반복하고 내부는 제품을 반복 할 것입니다.