Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/180.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何根据数据库列中的值使用数据填充datagridview_Sql_Datagridview_Visual Foxpro - Fatal编程技术网

Sql 如何根据数据库列中的值使用数据填充datagridview

Sql 如何根据数据库列中的值使用数据填充datagridview,sql,datagridview,visual-foxpro,Sql,Datagridview,Visual Foxpro,假设我有一个数据库表“用法”,如下所示: MACHINE WEEK HOURS PIECES A 2018-12 1 2 B 2018-12 3 4 A 2018-13 12 1 B 2018-13 2 5 A 2018-15 6

假设我有一个数据库表“用法”,如下所示:

MACHINE     WEEK        HOURS       PIECES
A           2018-12     1           2
B           2018-12     3           4
A           2018-13     12          1
B           2018-13     2           5
A           2018-15     6           6
B           2018-15     2           2
C           2018-16     2           1
D           2018-17     4           22
B           2018-17     3           9
A           2018-18     1           8
E           2018-18     4           4
D           2018-13     2           4
我想在datagridview中显示数据,如下所示:

MACHINE     2018-12     2018-13     2018-14     2018-15     2018-16     2018-17     2018-18
A           1H 2P       12H 1P                  6H 6P                               1H 8P
B           3H 4P       2H 5P                   2H 2P                   3H 9P
C                                                           2H 1P
D                       2H 4P                                           4H 22P
E                                                                                   4H 4P
在VisualFoxPro中,这非常简单

this.edType      = 1
this.ehCols      = 20
this.ehStartval  = date()+ 7
这在标题中创建了20个不同周数的列。然后,使用如下命令,您就完成了:

this.ehKeyFld    = "iif(usage.hours > 0 and usage.pieces > 0,STR(usage.hours,4) + 'H ' + STR(usage.pieces,3)+'P','')"
现在我想做同样的事情,但我喜欢在datagridview中显示数据

如果我这样做:

select machine, iif(week='2018-12',str(hours,4) + 'H' + str(pieces,3) + 'P','') as '2018-12', IIF(week='2018-13',str(hours,4) + 'H' + str(pieces,3) + 'P','') as '2018-13', IIF(week='2018-14',str(hours,4) + 'H' + str(pieces,3) + 'P','') as '2018-14', IIF(week='2018-15',str(hours,4) + 'H' + str(pieces,3) + 'P','') as '2018-15', IIF(week='2018-16',str(hours,4) + 'H' + str(pieces,3) + 'P','') as '2018-16', IIF(week='2018-17',str(hours,4) + 'H' + str(pieces,3) + 'P','') as '2018-17', IIF(week='2018-18',str(hours,4) + 'H' + str(pieces,3) + 'P','') as '2018-18' from GCCTEST.dbo.usage
我得到以下输出:

machine 2018-12 2018-13 2018-14 2018-15 2018-16 2018-17 2018-18
A       1H  2P                      
B       3H  4P                      
A               12H  1P                 
B               2H  5P                  
A                               6H  6P          
B                               2H  2P          
C                                       2H  1P      
D                                               4H 22P  
B                                               3H  9P  
A                                                       1H  8P
E                                                       4H  4P
D               2H  4P                  

我正在寻找SQL中的一个命令,它可以以我想要的方式填充datagridview,即每台机器一行都有正确列中的数据。

我接受使用VFP会更容易。但是,如果说datagridview,我想你指的是C#,这在很多方面也可以用C#实现。对于SQL,您还可以使用“PIVOT”。即:

但是,您不希望在SQL中硬编码所有这些列。检查“动态枢轴”。以下是来自Northwind数据的示例:

DECLARE @COUNTRY NVARCHAR(MAX) = '' , @cTotal NVARCHAR(MAX) = ''

SELECT  @COUNTRY = @COUNTRY + COALESCE(QUOTENAME(Country) + ', ', '')
FROM    Customers
WHERE   EXISTS ( SELECT *
                 FROM   [Orders] AS [o]
                 WHERE  o.[CustomerID] = Customers.[CustomerID] )
GROUP BY Country;

SET @COUNTRY = LEFT(@COUNTRY, LEN(@COUNTRY) - 1);

SELECT  @cTotal = @cTotal + COALESCE('Coalesce('+QUOTENAME(Country) + ',0) +', '')
FROM    Customers
WHERE   EXISTS ( SELECT *
                 FROM   [Orders] AS [o]
                 WHERE  o.[CustomerID] = Customers.[CustomerID] )
GROUP BY Country;

SET @cTotal = LEFT(@cTotal, LEN(@cTotal) - 1);

DECLARE @SQL NVARCHAR(MAX);

SET @SQL = 'SELECT * , ' + @cTotal + ' AS TOTAL FROM 
    (
        SELECT  oe.EmployeeID, oe.LastName, oe.ShipCountry AS CO,
                OD.Quantity * OD.UnitPrice AS QU
        FROM    (
                  SELECT  EmployeeID, LastName, ShipCountry
                  FROM    (
                            SELECT DISTINCT
                                    ShipCountry
                            FROM    Orders
                          ) o ,
                          Employees
                ) oe
        LEFT JOIN Orders O ON O.EmployeeID = oe.EmployeeID AND
                              [oe].[ShipCountry] = [O].[ShipCountry]
        LEFT JOIN [Order Details] OD ON OD.OrderID = O.OrderID 
    ) AS T
    PIVOT(SUM(QU) FOR CO IN (' + @COUNTRY + ')) AS PVT
    ORDER BY 1';

EXEC(@SQL); 

我接受使用VFP会更容易。但是,如果说datagridview,我想你指的是C#,这在很多方面也可以用C#实现。对于SQL,您还可以使用“PIVOT”。即:

但是,您不希望在SQL中硬编码所有这些列。检查“动态枢轴”。以下是来自Northwind数据的示例:

DECLARE @COUNTRY NVARCHAR(MAX) = '' , @cTotal NVARCHAR(MAX) = ''

SELECT  @COUNTRY = @COUNTRY + COALESCE(QUOTENAME(Country) + ', ', '')
FROM    Customers
WHERE   EXISTS ( SELECT *
                 FROM   [Orders] AS [o]
                 WHERE  o.[CustomerID] = Customers.[CustomerID] )
GROUP BY Country;

SET @COUNTRY = LEFT(@COUNTRY, LEN(@COUNTRY) - 1);

SELECT  @cTotal = @cTotal + COALESCE('Coalesce('+QUOTENAME(Country) + ',0) +', '')
FROM    Customers
WHERE   EXISTS ( SELECT *
                 FROM   [Orders] AS [o]
                 WHERE  o.[CustomerID] = Customers.[CustomerID] )
GROUP BY Country;

SET @cTotal = LEFT(@cTotal, LEN(@cTotal) - 1);

DECLARE @SQL NVARCHAR(MAX);

SET @SQL = 'SELECT * , ' + @cTotal + ' AS TOTAL FROM 
    (
        SELECT  oe.EmployeeID, oe.LastName, oe.ShipCountry AS CO,
                OD.Quantity * OD.UnitPrice AS QU
        FROM    (
                  SELECT  EmployeeID, LastName, ShipCountry
                  FROM    (
                            SELECT DISTINCT
                                    ShipCountry
                            FROM    Orders
                          ) o ,
                          Employees
                ) oe
        LEFT JOIN Orders O ON O.EmployeeID = oe.EmployeeID AND
                              [oe].[ShipCountry] = [O].[ShipCountry]
        LEFT JOIN [Order Details] OD ON OD.OrderID = O.OrderID 
    ) AS T
    PIVOT(SUM(QU) FOR CO IN (' + @COUNTRY + ')) AS PVT
    ORDER BY 1';

EXEC(@SQL); 

我也发现在SQL中更难做到,而.Net缺少VFP的动态性,您仍然可以通过自定义数据透视来解决这个问题。在VFP中,轴通常称为交叉表。实际上,它是对数据进行汇总,然后分发到列中,其中一列值(此处为机器)被转换为列。在您的示例中,数据已经汇总,实际上不需要使用MS SQL的pivot。IMHO获取数据并在数据表中本地创建交叉表是可以的,因为您只有大约20-25列(周),可能最多有1000台机器。以下是采样代码(代码是使用telerik代码转换器从C#转换而来的-注意:我从昨天开始使用MS SQL server base query只是为了模拟您的数据将来自MS SQL):


我也发现在SQL中更难做到,而.Net缺少VFP的动态性,您仍然可以通过自定义数据透视来解决这个问题。在VFP中,轴通常称为交叉表。实际上,它是对数据进行汇总,然后分发到列中,其中一列值(此处为机器)被转换为列。在您的示例中,数据已经汇总,实际上不需要使用MS SQL的pivot。IMHO获取数据并在数据表中本地创建交叉表是可以的,因为您只有大约20-25列(周),可能最多有1000台机器。以下是采样代码(代码是使用telerik代码转换器从C#转换而来的-注意:我从昨天开始使用MS SQL server base query只是为了模拟您的数据将来自MS SQL):

我的解决方案: 我有一个数据库,其中包含TBL机器中的机器描述,还有一个数据库包含tblUsage中机器的使用情况。 在我的windows窗体上,我有一个datagridview Dgv_4和一个Combobox1

' Separate class to do the sql command
Public SQL As New SQLControl
Private Dgv_4Query As String = $"m.id,m.listorder,m.prio,m.machine as 'Machine',m.weekuren as 'Hour/wk', week, STR(u.HOURS, len(u.HOURS))+'h_'+STR(u.PIECES, len(u.PIECES))+'p' as data FROM {GV.DB}tblMachines m "
Private Dgv_4Join As String = $"LEFT JOIN {GV.DB}tblUsage u on m.machine = u.machine "
Private Dgv_4Pivot As String = ""
Private EmptyQueryStringDgv_4 As String = ""
Private TotNumWeeks As Integer = 15

Private Sub DataGridViewForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    MdiParent = Main
    ' Create headers for datagridview with dates and weeknumbers starting with current week
    Dim WeekNumber As Integer = DatePart(DateInterval.WeekOfYear, Date.Now, FirstDayOfWeek.Monday, FirstWeekOfYear.System)
    ' First part of the pivot command
    Dim PivotString As String = $"PIVOT (MAX(data) FOR week IN("
    Dim endline As String = ","
    ' Middle part of the pivot command
    For i As Integer = 0 To TotNumWeeks
        If i = TotNumWeeks Then
            ' Last part of the pivot command
            endline = ")) as mypivot"
        End If
        PivotString = PivotString + $"[{Date.Today.Year}-{WeekNumber + i}]{endline}"
    Next
    Dgv_4Pivot = PivotString
    EmptyQueryStringDgv_4 = $"SELECT * FROM (SELECT {Dgv_4Query}{Dgv_4Join}) as source {Dgv_4Pivot} order by prio"
    LoadDataGridView1()
    ' Load combobox with current week
    ComboBox1.Items.Clear()
    ComboBox1.Text = $"{Date.Today.Year}-{WeekNumber}"
End Sub

Public Sub LoadDataGridView1(Optional ByVal QueryString As String = "", Optional ByVal Parameter As String = "")
    Dim dgvclass As New DataGridViewClass()
    Dim dname As DataGridView = Dgv_4
    Dim SelectRow As Integer = 0
    If QueryString = "" Then
        ' Default query
        QueryString = EmptyQueryStringDgv_4
    End If
    ' Use the sql command to request the data
    dgvclass.FillDataGridView(QueryString, Parameter, "Normal") = dname
    ' Hide column(s)
    dname.Columns(0).Visible = False
    dname.Columns(1).Visible = False
    ResizeGrid.ResizeGrid(dname, dname.Width)
End Sub
这将显示并加载从当前周开始的datagridview,通过一个组合框,您可以选择不同的周:

Private Sub ComboBox_Drop(sender As Object, e As EventArgs) Handles ComboBox1.DropDown
    Dim ac As ComboBox = DirectCast(sender, ComboBox)
    If Me.ActiveControl Is ComboBox1 Then
        ComboBox1.Items.Clear()
        ' Fill combobox with a range of weeks to chose from
        For i As Integer = -1 To 1 Step 1
            For j As Integer = 1 To 52
                Dim num As String = j.ToString
                If Len(num) < 2 Then
                    num = $"0{num}"
                End If
                ComboBox1.Items.Add(Date.Today.Year + i & "-" & num)
            Next
        Next
    End If
End Sub

Private Sub ComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
    ' Create headers for datagridview with dates and weeknumbers
    Dim result As String = ComboBox1.SelectedItem
    Dim PivotString As String = $"PIVOT (MAX(data) FOR week IN("
    Dim endline As String = ","
    Dim weekadd As Integer = 0
    For i As Integer = 0 To TotNumWeeks
        If i = TotNumWeeks Then
            ' Close string
            endline = ")) as mypivot"
        Else
            ' Check year limits
            If (Convert.ToInt32(Strings.Right(result, 2)) + i) > 52 Then
                ' Change year and week
                weekadd = 0
                result = $"{Convert.ToInt32(Strings.Left(result, 4)) + 1.ToString}-01"
            End If
        End If
        PivotString = PivotString + $"[{Strings.Left(result, 4)}-{(Convert.ToInt32(Strings.Right(result, 2)) + weekadd).ToString("D2")}]{endline}"
        weekadd = weekadd + 1
    Next
    Dgv_4Pivot = PivotString
    ' Run query without pivot, seems to prevent insert columns on the right
    LoadDataGridView1($"SELECT {Dgv_4Query}{Dgv_4Join}")
    ' Run query with pivot to fill datagridview with new weeks
    LoadDataGridView1($"SELECT * FROM (SELECT {Dgv_4Query}{Dgv_4Join}) as source {Dgv_4Pivot} order by prio", "")
End Sub
Private子组合框\u Drop(发送方作为对象,e作为事件参数)处理组合框1.DropDown
Dim ac As ComboBox=DirectCast(发送方,ComboBox)
如果Me.ActiveControl是ComboBox1,则
ComboBox1.Items.Clear()
'用可供选择的周数填充组合框
对于i作为整数=-1到1步骤1
对于j,作为整数=1到52
作为字符串的Dim num=j.ToString
如果Len(num)<2,则
num=$“0{num}”
如果结束
ComboBox1.Items.Add(Date.Today.Year+i&“-”&num)
下一个
下一个
如果结束
端接头
私有子组合框\u SelectedIndexChanged(发送方作为对象,e作为事件参数)处理组合框1.SelectedIndexChanged
'使用日期和周数为datagridview创建标题
将结果设置为字符串=ComboBox1.SelectedItem
Dim PivotString As String=$“数据透视(数据透视)在(”
作为字符串的Dim endline=“,”
Dim weekadd作为整数=0
对于i,整数=0到整数周
如果i=totnumweek,那么
'闭合字符串
endline=“))作为mypivot”
其他的
“检查年份限制
如果(Convert.ToInt32(Strings.Right(result,2))+i)>52,那么
“年复一年,周而复始
weekadd=0
结果=$“{Convert.ToInt32(Strings.Left(result,4))+1.ToString}-01”
如果结束
如果结束
PivotString=PivotString+$“[{Strings.Left(result,4)}-{(Convert.ToInt32(Strings.Right(result,2))+weekadd.ToString(“D2”)}]{endline}”
weekadd=weekadd+1
下一个
Dgv_4Pivot=数据透视字符串
'不使用透视运行查询,似乎会阻止在右侧插入列
LoadDataGridView1($“选择{Dgv_4Query}{Dgv_4Join}”)
'使用pivot运行查询,用新的周数填充datagridview
LoadDataGridView1($“选择*自(选择{Dgv_4Query}{Dgv_4Join})作为源{Dgv_4Pivot}按优先级排序”,“”)
端接头
输出示例:

我的解决方案: 我有一个数据库,其中包含TBL机器中的机器描述,还有一个数据库包含tblUsage中机器的使用情况。 在我的windows窗体上,我有一个datagridview Dgv_4和一个Combobox1

' Separate class to do the sql command
Public SQL As New SQLControl
Private Dgv_4Query As String = $"m.id,m.listorder,m.prio,m.machine as 'Machine',m.weekuren as 'Hour/wk', week, STR(u.HOURS, len(u.HOURS))+'h_'+STR(u.PIECES, len(u.PIECES))+'p' as data FROM {GV.DB}tblMachines m "
Private Dgv_4Join As String = $"LEFT JOIN {GV.DB}tblUsage u on m.machine = u.machine "
Private Dgv_4Pivot As String = ""
Private EmptyQueryStringDgv_4 As String = ""
Private TotNumWeeks As Integer = 15

Private Sub DataGridViewForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    MdiParent = Main
    ' Create headers for datagridview with dates and weeknumbers starting with current week
    Dim WeekNumber As Integer = DatePart(DateInterval.WeekOfYear, Date.Now, FirstDayOfWeek.Monday, FirstWeekOfYear.System)
    ' First part of the pivot command
    Dim PivotString As String = $"PIVOT (MAX(data) FOR week IN("
    Dim endline As String = ","
    ' Middle part of the pivot command
    For i As Integer = 0 To TotNumWeeks
        If i = TotNumWeeks Then
            ' Last part of the pivot command
            endline = ")) as mypivot"
        End If
        PivotString = PivotString + $"[{Date.Today.Year}-{WeekNumber + i}]{endline}"
    Next
    Dgv_4Pivot = PivotString
    EmptyQueryStringDgv_4 = $"SELECT * FROM (SELECT {Dgv_4Query}{Dgv_4Join}) as source {Dgv_4Pivot} order by prio"
    LoadDataGridView1()
    ' Load combobox with current week
    ComboBox1.Items.Clear()
    ComboBox1.Text = $"{Date.Today.Year}-{WeekNumber}"
End Sub

Public Sub LoadDataGridView1(Optional ByVal QueryString As String = "", Optional ByVal Parameter As String = "")
    Dim dgvclass As New DataGridViewClass()
    Dim dname As DataGridView = Dgv_4
    Dim SelectRow As Integer = 0
    If QueryString = "" Then
        ' Default query
        QueryString = EmptyQueryStringDgv_4
    End If
    ' Use the sql command to request the data
    dgvclass.FillDataGridView(QueryString, Parameter, "Normal") = dname
    ' Hide column(s)
    dname.Columns(0).Visible = False
    dname.Columns(1).Visible = False
    ResizeGrid.ResizeGrid(dname, dname.Width)
End Sub
这将显示并加载从当前周开始的datagridview,通过一个组合框,您可以选择不同的周:

Private Sub ComboBox_Drop(sender As Object, e As EventArgs) Handles ComboBox1.DropDown
    Dim ac As ComboBox = DirectCast(sender, ComboBox)
    If Me.ActiveControl Is ComboBox1 Then
        ComboBox1.Items.Clear()
        ' Fill combobox with a range of weeks to chose from
        For i As Integer = -1 To 1 Step 1
            For j As Integer = 1 To 52
                Dim num As String = j.ToString
                If Len(num) < 2 Then
                    num = $"0{num}"
                End If
                ComboBox1.Items.Add(Date.Today.Year + i & "-" & num)
            Next
        Next
    End If
End Sub

Private Sub ComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
    ' Create headers for datagridview with dates and weeknumbers
    Dim result As String = ComboBox1.SelectedItem
    Dim PivotString As String = $"PIVOT (MAX(data) FOR week IN("
    Dim endline As String = ","
    Dim weekadd As Integer = 0
    For i As Integer = 0 To TotNumWeeks
        If i = TotNumWeeks Then
            ' Close string
            endline = ")) as mypivot"
        Else
            ' Check year limits
            If (Convert.ToInt32(Strings.Right(result, 2)) + i) > 52 Then
                ' Change year and week
                weekadd = 0
                result = $"{Convert.ToInt32(Strings.Left(result, 4)) + 1.ToString}-01"
            End If
        End If
        PivotString = PivotString + $"[{Strings.Left(result, 4)}-{(Convert.ToInt32(Strings.Right(result, 2)) + weekadd).ToString("D2")}]{endline}"
        weekadd = weekadd + 1
    Next
    Dgv_4Pivot = PivotString
    ' Run query without pivot, seems to prevent insert columns on the right
    LoadDataGridView1($"SELECT {Dgv_4Query}{Dgv_4Join}")
    ' Run query with pivot to fill datagridview with new weeks
    LoadDataGridView1($"SELECT * FROM (SELECT {Dgv_4Query}{Dgv_4Join}) as source {Dgv_4Pivot} order by prio", "")
End Sub
Private子组合框\u Drop(发送方作为对象,e作为事件参数)处理组合框1.DropDown
Dim ac As ComboBox=DirectCast(发送方,ComboBox)
如果Me.ActiveControl是ComboBox1,则
ComboBox1.Items.Clear()
'用可供选择的周数填充组合框
对于i作为整数=-1到1步骤1
对于j As Inte