I have relational database. Each students has different history(one to many). The data is correct but the problem here is that student information become repetitive when loading in datagridview.I use DISTINCT function but it does not work. Can someone help me to figure out what's wrong with my code.
vb.net code when load
Using cmd As New SqlClient.SqlCommand("dbo.uspSELECTALL", cn)
da.SelectCommand = cmd
dt.Clear()
da.Fill(dt)
dgv1.RowTemplate.Height = 50
dgv1.DataSource = dt
For i As Integer = 0 To dgv1.Columns.Count - 1
If TypeOf dgv1.Columns(i) Is DataGridViewImageColumn Then
DirectCast(dgv1.Columns(i), DataGridViewImageColumn).ImageLayout = DataGridViewImageCellLayout.Stretch
End If
Next
End Using
stored procedure code
ALTER PROCEDURE [dbo].[uspSELECTALL]
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT SI.StudentID,SI.Surname,SI.FirstName,SI.MiddleName, SI.StudAddress ,
SI.BirthDay,SI.Gender, SI.Nationality, SI.BirthPlace,
SI.TelNum,SI.SchoolWhereGraduated ,
SI.DatesWhenGraduated, SI.SchoolLastAttended,
SI.Note,SI.StudImage,
PI.Father_FirstName,PI.Father_LastName,
PI.Father_MI,PI.Father_Occupation,
PI.Father_TelNUm, PI.Mother_FirstName, PI.Mother_LastName,
PI.Mother_MI,PI.Mother_Occupation,PI.Mother_TelNum,
PI.Contact_FirstName,PI.Contact_LastName,PI.Contact_MI,
PI.Contact_Mobile,PI.Contact_TelNum,PI.Contact_Address,
SH.SchoolYear,SH.Levels,SH.Section,SH.DateEnrolled
FROM StudentInformation SI
JOIN StudentHistory SH
ON SI.StudentID = SH.StudentID
JOIN ParentInformation PI
ON PI.ParentID = SI.ParentID
END
If you want show in the DataGridView only distincts id's of students,
then you need use another query.
Your current query always return multiply rows per student if student have more then one history.
One approach will be removing all columns of table StudentHistory from SELECT statement and keep DISTINCTkeyword in the query.
SELECT DISTINCT SI.StudentID,SI.Surname,SI.FirstName,SI.MiddleName, SI.StudAddress ,
SI.BirthDay,SI.Gender, SI.Nationality, SI.BirthPlace,
SI.TelNum,SI.SchoolWhereGraduated ,
SI.DatesWhenGraduated, SI.SchoolLastAttended,
SI.Note,SI.StudImage,
PI.Father_FirstName,PI.Father_LastName,
PI.Father_MI,PI.Father_Occupation,
PI.Father_TelNUm, PI.Mother_FirstName, PI.Mother_LastName,
PI.Mother_MI,PI.Mother_Occupation,PI.Mother_TelNum,
PI.Contact_FirstName,PI.Contact_LastName,PI.Contact_MI,
PI.Contact_Mobile,PI.Contact_TelNum,PI.Contact_Address
FROM StudentInformation SI
JOIN StudentHistory SH
ON SI.StudentID = SH.StudentID
JOIN ParentInformation PI
ON PI.ParentID = SI.ParentID
Another way will be filter DataTable which was filled by your query.
Using cmd As New SqlClient.SqlCommand("dbo.uspSELECTALL", cn)
da.SelectCommand = cmd
dt.Clear()
da.Fill(dt)
dgv1.RowTemplate.Height = 50
'Filtering for distinct rows
Dim view As New DataView(GetData())
Dim distinctColumnNames As String() =
{
"StudentID", "Surname", "FirstName", "MiddleName",
"StudAddress" ' and so on
}
Dim distinctValues As DataTable = view.ToTable(True, distinctColumnNames)
dgv1.DataSource = distinctValues
'Your other code
End Using
view.ToTable(True, distinctColumnNames) if first parameter is True then only distinct rows, based on columnnames will be included
Related
In VB.NET am trying to return all databases that have a specific table. The code I have been using polls just the databases and that works fine. When I add the CASE statement below to get just the ones with the table I need then it returns nothing.
strQuery = "SELECT [name] FROM sys.databases where create_date > '2016-07-01' and [name] not like '_Config_Options' order by create_date desc"
sqlCon = New SqlConnection(strConn)
Using (sqlCon)
Dim sqlComm As SqlCommand = New SqlCommand(strQuery, sqlCon)
sqlCon.Open()
Dim sqlReader As SqlDataReader = sqlComm.ExecuteReader
If sqlReader.HasRows Then
While (sqlReader.Read())
cmbDatabase.Items.Add(sqlReader.GetString(0))
End While
End If
sqlReader.Close()
End Using
The above code returns the full list of databases.
When I change the strQuery to
strQuery = "SELECT [name] FROM sys.databases WHERE CASE WHEN state_desc = ''ONLINE'' THEN OBJECT_ID(QUOTENAME([name]) + ''.[dbo].[MyTable]'', ''U'') END IS NOT NULL order by create_date desc"
I get nothing back. After executing Dim sqlReader As SqlDataReader = sqlComm.ExecuteReader, the code jumps to the End Using. I don't see an error code.
Joel Coehoom gets the credit for answering. I removed the double single quotes and it works.
strQuery = "SELECT [name] FROM sys.databases WHERE CASE WHEN state_desc = 'ONLINE' THEN OBJECT_ID(QUOTENAME([name]) + '.[dbo].[MyTable]', 'U') END IS NOT NULL order by create_date desc"
The function below is trying to get the earliest date from a table with 3 dates, one for each type of user, care, sales and manager. This is to build up the diary system by first finding the first date in the diary dates. It's working for some users, but in one case the values do not return at and it gives null.
Private Function GetEarliestDate() As Date
Dim strSQL As String
Dim cmd As New SqlCommand
Dim dDate As Date
Try
strSQL = "Select dT.RecordID, MIN(dT.inDate) As [EarliestDate]
FROM (
Select RecordID, SentDate As [inDate]
From tblOrderDetails Where Flagged = 0 AND SalesID = '" & gUserID & "'
UNION ALL
Select RecordID, DiaryDate AS [inDate]
From tblOrderDetails
Where Flagged=0 And ManID ='" & gUserID & "'
UNION ALL
Select RecordID, CareDate As [inDate]
From tblOrderDetails
Where Flagged = 0 And CareID ='" & gUserID & "'
) As dT Group By RecordID"
cmd.CommandText = strSQL
cmd.Connection = CnMaster
cmd.CommandType = CommandType.Text
Dim RecordCount As Integer
RecordCount = 0
dDate = DateTime.MaxValue
Using reader As SqlDataReader = cmd.ExecuteReader()
While (reader.Read())
RecordCount += 1
Dim dt As DateTime = reader.GetDateTime(1)
If dt < dDate Then
dDate = dt
End If
End While
If dDate = DateTime.MaxValue Then
dDate = DateTime.MinValue
End If
End Using
cmd.Dispose()
Return dDate
Catch ex As Exception
Error_Handler(ex, "GetEarliestDate", "Unable to Get The Earliest Date!")
End Try
Put in all 3 queries additional where:
where SentDate is not null ...
where DiaryDate is not null ...
where CareDate is not null ...
I have four tables. The purpose of this code is for user to select a customer from a combobox and the check the shipments going to that customer to put into the FormHeaderTable. Let's pretend two shipments get selected.... forms can have several Shipments. Shipments can have several partnumbers
Table 1: FormHeaderTable
FormID (pk)
OrderKey(pk) (keeps track of how many forms have been made for a specific customer)
CreationDate
CustomerName
Table 2: FormLineTable
LineID (pk)
FormID, (pk, fk) (comes from FormHeaderTable)
OrderKey (pk, fk) (comes from FormHeaderTable)
ShipmentNumber (pk, fk) (comes from ShipmentHeaderTable)
PartNumber
Table 3: ShipmentHeaderTable
ShipmentNumber (pk) (rest of columns not needed for this question, just shipment details)
Table4: ShipmentLineTable
ShipmentLine (PK)
ShipmentNumber(PK, FK) (comes from shipmentHeaderTable)
PartNumber
I need to insert values into my FormLineTable based on the ShipmentNumbers selected from a checklistbox that is populated by a customer combobox's selection.
I tried to do this:
Dim OrderKey As Integer
Dim LastFormID As Integer
Dim NextFormID As Integer
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Get FormID and Get OrderKey
Dim MAXOrderKey As String = "SELECT MAX(OrderKey) FROM FormHeaderTable WHERE CustomerName = #CustomerName"
Dim MAXOrderKeyCommand As New SqlCommand(MAXOrderKey, con)
Dim MAXFormID As String = "Select MAX(FormID) FROM FormHeaderTable"
Dim MAXFormIDCommand As New SqlCommand(MAXFormID, con)
MAXOrderKeyCommand.Parameters.Add("#CustomerName", SqlDbType.VarChar).Value = cboCustomer.Text
If con.State = ConnectionState.Closed Then con.Open()
Try
LastFormID = CInt(MAXFormIDCommand.ExecuteScalar)
Catch ex As System.Exception
LastFormID = 0
End Try
Try
OrderKey = CInt(MAXOrderKeyCommand.ExecuteScalar)
Catch ex As System.Exception
OrderKey = 0
End Try
con.Close()
NextFormID = LastFormID + 1
OrderKey = OrderKey + 1
Dim cmd As New SqlCommand("SET IDENTITY_INSERT FormHeadertable ON Insert INTO FormHeaderTable (FormID, CustomerName, CreationDate, OrderKey) Values (#FormID, #CustomerName, #CreationDate, #OrderKey) SET IDENTITY_INSERT FormHeadertable OFF ", con)
cmd.Parameters.Add("#FormID", SqlDbType.Int).Value = NextFormID
cmd.Parameters.Add("#CustomerName", SqlDbType.VarChar).Value = cboCustomer.Text
cmd.Parameters.Add("#CreationDate", SqlDbType.Date).Value = Date.Now()
cmd.Parameters.Add("#OrderKey", SqlDbType.Int).Value = OrderKey
'this is where I need help'
Dim cmd1 As New SqlCommand("Insert into FormLineTable (FormID, OrderKey, LineId, ShipmentNumber, PartNumber) Select FormID, OrderKey, ShipmentLineNumber, ShipmentNumber, PartNumber FROM ShipmentLineTable CROSS JOIN FormHeaderTable", con)
cmd1.Parameters.Add("#FormID", SqlDbType.Int).Value = NextFormID
cmd1.Parameters.Add("#OrderKey", SqlDbType.Int).Value = OrderKey
Dim isFirst As Boolean = True
For i As Integer = 0 To chkLstShipments.Items.Count - 1
If chkLstShipments.GetItemCheckState(i) = CheckState.Checked Then
If isFirst = True Then
cmd1.CommandText += " WHERE ShipmentNumber = #ShipmentNumber" + i.ToString
isFirst = False
Else
cmd1.CommandText += " OR ShipmentNumber = #ShipmentNumber" + i.ToString
End If
cmd1.Parameters.Add("#ShipmentNumber" + i.ToString, SqlDbType.Int).Value = chkLstShipments.Items(i)
End If
Next
If con.State = ConnectionState.Closed Then con.Open()
cmd.ExecuteNonQuery()
cmd1.ExecuteNonQuery()
con.Close()
End Sub
My error
36 duplicate values or so...
Got rid of cross join section. switched FormId and OrderKey to the variables #FormId and #OrderKey and filled in these two variables with the variables I defined earlier in the code: NextNaftaId and OrderKey
New code looks like this:
Dim cmd1 As New SqlCommand("Insert into FormLineTable (FormID, OrderKey, LineId, ShipmentNumber, PartNumber) Select #FormID, #OrderKey, ShipmentLineNumber, ShipmentNumber, PartNumber FROM ShipmentLineTable", con)
cmd1.Parameters.Add("#FormID", SqlDbType.Int).Value = NextFormID
cmd1.Parameters.Add("#OrderKey", SqlDbType.Int).Value = OrderKey
I'm trying to retrieve data from this SQL Server stored procedure from a vb class and on the class:
Dim GetDailySalesAmateurRptOrderItems_DataArray(,) As String =
oDAL.GetDailySalesAmateurRptOrderItems("2014-04-17", "2014-04-20")
Even though there is enough data in the database it returns nothing to the array... any idea what is causing this problem?
USE [QUICKFIX_COLOR_LAB_POS]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[GetDailySalesAmateurRptOrderItems]
#FromDate Datetime, #ToDate Datetime
as
SELECT
ITEMS.ItemID, ITEMS.ItemName, ORDER_ITEMSET.Qty,
ORDER_ITEMSET.SoldPrice, ORDERS.OrderTimestamp
FROM
ORDERS
INNER JOIN
ORDER_ITEMSET ON ORDERS.OrderID = ORDER_ITEMSET.OrderID
INNER JOIN
CUSTOMER_ACCOUNTS ON ORDERS.CustomerID = CUSTOMER_ACCOUNTS.CUSTOMER_ID
CROSS JOIN
ITEMS
WHERE
(CUSTOMER_ACCOUNTS.CUSTOMER_CATEGORY = 'Amateur')
AND (ORDERS.OrderTimestamp BETWEEN CONVERT(DATETIME, #FromDate, 102) AND CONVERT(DATETIME, #ToDate, 102))
ORDER BY
ITEMS.ItemID
VB function
Function GetDailySalesAmateurRptOrderItems(DateFrom As String, ByVal DateTo As String)
Try
Dim DateFrom_Date As DateTime = DateFrom
Dim DateTo_Date As DateTime = DateTo
Dim output(,) As String
Dim counter As Integer
Dim cmd As New SqlCommand("GetDailySalesAmateurRptOrderItems", DBconn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#FromDate", DateFrom_Date)
cmd.Parameters.AddWithValue("#ToDate", DateTo_Date)
Dim reader As SqlDataReader
DBconn.Open()
reader = cmd.ExecuteReader
While reader.Read()
counter = counter + 1
End While
ReDim output(counter - 1, 0 To 4)
counter = 0
reader.Close()
reader = cmd.ExecuteReader
While reader.Read()
output(counter, 0) = reader(0)
output(counter, 1) = reader(1)
output(counter, 2) = reader(2)
output(counter, 3) = reader(3)
output(counter, 4) = reader(4)
counter = counter + 1
End While
DBconn.Close()
Return output
Catch ex As Exception
Return ex.Message
End Try
End Function
In stored procedure MS SQL My query is:
SELECT *
FROM ContentReportRequests a,UserPreferences d
WHERE a.UserID = d.UserID and a.ID =#ID
I want to give the result table some name.
How can I do this ?
I want to pull it to ADO.Net DataSet.tables["NAME"]
I can imagine a few things you might be meaning.
If you want to persist this result set, for consumption in multiple later queries, you might be looking for SELECT INTO:
SELECT * into NewTableName
FROM ContentReportRequests a,UserPreferences d
WHERE a.UserID = d.UserID and a.ID =#ID
Where NewTableName is a new name, and a new (permanent) table will be created. If you want that table to go away when you're finished, prefix the name with a #, to make it a temp table.
Alternatively, you might just be wanting to absorb it into a single larger query, in which case you'd be looking at making it a subselect:
SELECT *
FROM (SELECT *
FROM ContentReportRequests a,UserPreferences d
WHERE a.UserID = d.UserID and a.ID =#ID
) NewTableName
WHERE NewTableName.ColumnValue = 'abc'
or a CTE:
WITH NewTableName AS (
SELECT *
FROM ContentReportRequests a,UserPreferences d
WHERE a.UserID = d.UserID and a.ID =#ID
)
SELECT * from NewTableName
Finally, you might be talking about pulling the result set into e.g. an ADO.Net DataTable, and you want the name to be set automatically. I'm not sure that that is feasible.
You can use a variable of type table. Read more here: Table Variables In T-SQL
in stored procedure:
select CH.PrimaryKey, CH.Name,
NULL "CustomerHeader"
from CustomerHeader "CH";
--
select CD.PrimaryKey, CD.ShipTo,
NULL "CustomerDetail"
from CustomerDetail "CD";
--
select *, NULL "Orders"
from OrderTable;
in Vb.Net code:
Dim ds As DataSet = Nothing
ds = SqlExecute();
Dim dtCustHeader As DataTable = Nothing
Dim dtCustDetail As DataTable = Nothing
Dim dtOrders As DataTable = Nothing
For Each dt As DataTable In ds.tables
Select Case True
Case dt.Columns.Contains("CustomerHeader")
dtCustHeader = dt
Case dt.Columns.Contains("CustomerDetail")
dtCustDetail = dt
Case dt.Columns.Contains("Orders")
dtOrders = dt
End Select
Next
Kinda SILLY (OR STUPID) that you cannot name tables in a result set.
But this gets you there without a HUGE byte count repeating the table name within each row.
There is still overhead passing the NULL value back for each row. Perhaps passing a BIT value would be smaller yet...
And an alternative is to always use column(0):
in SQL:
select NULL "CustomerDetail", CustName,Addr1,Addr2... from CustomerDetail;
in vb.net:
Dim ds As DataSet = Nothing
ds = SqlExecute();
Dim dtCustHeader As DataTable = Nothing
Dim dtCustDetail As DataTable = Nothing
Dim dtOrders As DataTable = Nothing
For Each dt As DataTable In ds.Tables
Dim tblName As String = dt.Columns(0).ColumnName
Select Case tblName.ToUpper
Case "CUSTOMERDETAIL" : dtCustHeader = dt
Case "CUSTOMERDETAIL" : dtCustDetail = dt
Case "ORDERS" : dtOrders = dt
End Select
Next
These methods get your table-names even if the query returns zero rows.
but the best for last... a way to actually name the tables in the dataset automatically, every time FROM SQL STORED PROCEDURE (with help from your code):
Dim ds As DataSet = Nothing
ds = SqlExecute();
For Each dt As DataTable In ds.Tables
dt.TableName = dt.Columns(0).ColumnName
Next
After this, you may access your tables with the name YOU control within the stored procedure... as it should have been from day-one!
EDIT: selective implementation:
Name the first column in the pattern "TN:Customer".
Your legacy stored procedures work normally, only impacting the stored procedures you wish to modify.
For Each dt As DataTable In mo_LastDataset.Tables
Dim tblName() As String = dt.Columns(0).ColumnName.Split(":")
If tblName.Length >= 2 AndAlso tblName(0).ToUpper = "TN" Then
dt.TableName = tblName(1)
End If
Next
... david ...
SELECT * AS MyTableName
FROM ContentReportRequests a, UserPreferences d
WHERE a.UserID = d.UserID and a.ID =#ID