adding results of query against datatable to a column in another datatable in visual basic - sql

Problem: I have populated a datatable using a query on a sql server database. The query is:
Select ID, startDate, codeID, Param,
(select top 1 startDate from myTable
where ID='" & ID & "' and Param = mt.param and codeID = 82 and startDate >= '" & startDate & "' and startDate >=mt.startDate
ORDER BY startDate)endTime,
from myTable mt where ID = '" & ID & "'
AND (startDate between '" & startDate & "' AND '" & endDate & "' AND (codeID = 81))
I want a new column called duration that will be the difference between endTime and startDate in milliseconds. I can't just add another subquery to the above query since the endTime column didn't exist until the subquery was ran.
So, is there a way to maybe run the first query to populate the datatable, then run a query like:
Select DateDiff(ms,endTime,startDate)
On its own and add its results to a new column in my datatable?

You can always nest that in another query:
select *, datediff(ms, startDate, endTime)
from (
<your existing query here>
) t
And while I'm here, it seems you need a lesson in parameterized queries:
Dim result As New DataTable
Dim Sql As String = _
"SELECT *, datediff(ms, startDate, endTime) FROM (" & _
"SELECT ID, startDate, codeID, Param, " & _
"(select top 1 startDate from myTable " & _
"where ID= #ID and Param = mt.param and codeID = 82 and startDate >= #startDate and startDate >=mt.startDate " & _
"ORDER BY startDate) endTime " & _
" FROM myTable mt " & _
" WHERE ID = #ID AND startDate between #startDate AND #endDate AND codeID = 81" & _
") t"
Using cn As New SqlConnection("connection string"), _
cmd As New SqlCommand(sql, cn)
cmd.Parameters.Add("#ID", SqlDbType.VarChar, 10).Value = ID
cmd.Parameters.Add("#startDate", SqlDbType.DateTime).Value = Convert.ToDateTime(startDate)
cmd.Parameters.Add("#endDate", SqlDbType.DateTime).Value = Convert.ToDateTime(endDate)
cn.Open()
Using rdr = cmd.ExecuteReader()
result.Load(rdr)
rdr.Close()
End Using
End Using

Related

(Ms Access) Row_Number() Over Partition

How can I convert the row_number() function with an over partition on MS ACCESS? What I want to achieve is:
from this table:
ID | EntryDate
10 | 2016-10-10
10 | 2016-12-10
10 | 2016-12-31
10 | 2017-01-31
10 | 2017-03-31
11 | 2015-01-31
11 | 2017-01-31
To this output, showing only the top 3 latest of each ID:
ID | EntryDate
10 | 2016-12-31
10 | 2017-01-31
10 | 2017-03-31
11 | 2015-01-31
11 | 2017-01-31
On SQL Server, i can achieved this using the following code:
select T.[ID],
T.[AptEndDate],
from (
select T.[ID],
T.[AptEndDate],
row_number() over(partition by T.[ID] order by T.[AptEndDate] desc) as rn
from Table1 as T
) as T
where T.rn <= 3;
Consider a count correlated subquery which can work in any RDBMS.
select T.[ID], T.[EntryDate]
from
(select sub.[ID],
sub.[EntryDate],
(select count(*) from Table1 c
where c.ID = sub.ID
and c.[EntryDate] >= sub.[EntryDate]) as rn
from Table1 as sub
) as T
where T.rn <= 3;
It might be simpler and faster to use Top n - as you mention yourself:
Select T.[ID], T.[EntryDate]
From Table1 As T
Where T.[EntryDate] In
(Select Top 3 S.[EntryDate]
From Table1 As S
Where S.[ID] = T.[ID]
Order By S.[EntryDate] Desc)
Order By T.[ID] Asc, T.[EntryDate] Asc
Anything using the OVER clause is something known as a Windowing Function. Unfortunately, MS Access does not have support for Windowing Functions.The easiest solution in this case may be to back to VBA code :(
Public Const tableName As String = "[TransactionalData$]"
Public Const parentId As String = "parentId"
Public Const elementId As String = "Id"
Public Const informationalField As String = "Label"
Sub TransactionalQuery(Optional ByVal Id As Integer = 0)
Dim rs As New ADODB.Recordset, cn As New ADODB.Connection
Dim sqlString As String
''' setup the connection to the current Worksheet --- this can be changed as needed for a different data source, this example is for EXCEL Worksheet
cn.Open ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties='Excel 12.0 Macro;HDR=YES;IMEX=1'")
'''' Alternate method for the query
sqlString = "SELECT ParentId, Rank() OVER(PARTITION BY ParentId ORDER BY Label) , vlu.Id, vlu.Label FROM [TransactionalData$] var LEFT JOIN [TransactionalData$] vlu ON vlu.Id=var.ParentId"
''' will need to change the TableName (TransactionalData$]
sqlString = "SELECT DISTINCT " & elementId & " FROM " & tableName & " WHERE " & parentId & " = " & Id
rs.Open sqlString, cn, adOpenStatic, adLockReadOnly
'' Start collecting the SQL UNIONs to run at the end
sqlString = ""
Do While Not rs.EOF
'' Add current Element to the UNION
sqlString = sqlString & "SELECT * FROM " & tableName & " WHERE " & elementId & " = " & rs.Fields(elementId) & " UNION " & vbCrLf
'' Add all children element to the UNION
sqlString = sqlString & subQuery(cn, rs.Fields(elementId))
rs.MoveNext
Loop
rs.Close
'''Debug.Print sqlString
''' Remove the extra UNION keyword at the end
sqlString = Left(sqlString, Len(sqlString) - 8)
''' Exectue the built query
rs.Open sqlString, cn, adOpenStatic, adLockReadOnly
''Do While Not rs.EOF
'' Debug.Print rs.Fields(elementId) & ", " & rs.Fields(informationalField)
'' rs.MoveNext
''Loop
End Sub
Function subQuery(cn As ADODB.Connection, Id As Integer) As String
Dim sqlString As String
Dim subSqlString As String, rs As New ADODB.Recordset
'' Create a list of children for the current element
sqlString = "SELECT DISTINCT " & elementId & " FROM " & tableName & " WHERE " & parentId & " = " & Id
rs.Open sqlString, cn, adOpenStatic, adLockReadOnly
'' start the SQL for current elements children
sqlString = ""
Do While Not rs.EOF
''' add in the current element to the UNION
sqlString = sqlString & "SELECT * FROM " & tableName & " WHERE Id = " & rs.Fields(elementId) & " UNION " & vbCrLf
''' recursively find additional children for the current element
sqlString = sqlString & subQuery(cn, rs.Fields(elementId))
rs.MoveNext
Loop
rs.Close
''' return the SQL for the current element and all its children
subQuery = sqlString
End Function

String Constant must End with double quote SQL report

Below is the query for a sql report that I am completing in SQL Server Business Studio and I keep getting an error regarding the double quotes on this line Dim SelectClause as System.String = ""
I tried a few things but I get the repeating error.
Any help would be appreciated.
Function getSelectClause(ByVal startDate as DateTime, ByVal endDate as DateTime) as String
Dim SelectClause as System.String = ""
SelectClause ="SELECT Define.meterName, SUM(Reading.volume) AS [Total Volume], MIN(Reading.time) AS [Month]
FROM [Reading] INNER JOIN Define ON Reading.meterId = Define.meterId
WHERE (Reading.[time] >= " & startDate & " AND Reading.[time]< " & endDate & ")
AND Define.meterName IN ('007080')
AND (Reading.dataQuality = '11' OR
Reading.dataQuality = '10') AND (Reading.auditVersion = '0')
GROUP BY Define.meterName"
return SelectClause
End Function
SSRS uses VB as its language for custom functions, which has a different syntax that SQL. VB does not support multi-line statements like SQL does. You need to end each line with " + _ and begin the continuation with ", and change how you append the date strings :
Function getSelectClause(ByVal startDate as DateTime, ByVal endDate as DateTime) as String
Dim SelectClause as System.String = ""
SelectClause ="SELECT Define.meterName, SUM(Reading.volume) AS [Total Volume], " + _
" MIN(Reading.time) AS [Month]" + _
" FROM [Reading] INNER JOIN Define ON Reading.meterId = Define.meterId" + _
" WHERE (Reading.[time] >= '" + startDate + "' AND Reading.[time]< '" + endDate+ "')" + _
" AND Define.meterName IN ('007080')" + _
" AND (Reading.dataQuality = '11' OR " + _
" Reading.dataQuality = '10') AND (Reading.auditVersion = '0') " + _
" GROUP BY Define.meterName"
return SelectClause

How to pass parameter value to crystal report's data source

i got a stored procedure and i got it going in my crystal report
CREATE FUNCTION [dbo].[SP_MainContent]
( #from int,
#to int,
#year int,
#office varchar(MAX),
#fund varchar(MAX)
)
RETURNS TABLE
AS
RETURN (
SELECT AccntTbl.Id,
AccntTbl.accnt,
ISNULL(SupplyTbl.Supply, 0) AS Supply,
AccntTbl.office,
AccntTbl.exp,
AccntTbl.dateCreated
FROM AccntTbl
LEFT JOIN
(SELECT idAccnt,
SUM(amount) AS Supply
FROM SuppyTbl AS SupplyTbl1
WHERE MONTH(dateCreated) BETWEEN #from AND #to
AND YEAR(dateCreated) = #year
AND fund = #fund
GROUP BY idAccnt) AS SupplyTbl
WHERE YEAR(AccntTbl.dateCreated) = #year
AND AccntTbl.office = #office
AND AccntTbl.fund = #fund
GROUP BY AccntTbl.Id,
AccntTbl.accnt,
AccntTbl.appro,
Supply.Supply
);
and in VB.NET
Dim ad As New SqlDataAdapter("SP_MainContent '" & 1 & "', '" & 2 & "', '" & 2016 & "', " & _
" 'office', 'food'", conn)
Dim ds As New DataSet
Dim rpt As New CRreport
ad.Fill(ds, "SP_MainContent")
rpt.SetDataSource(ds)
CrystalReportViewer1.Refresh()
CrystalReportViewer1.ReportSource = rpt
but every time i open up the report this window will pop-up, its is so annoying.
how to stop this to pop up ? whenever i open up my report in vb.net
glad for any help..tnx :)
You should pass parameter values like below
rpt.SetParameterValue("#param_name", the_value)

Identical datatable 2 columns merging and summing one column in vb.net

I have 5 datatables which having each 3 columns (ID, Brand, Quanitiy) to derive the opening, purchase, sales and closing stock. The First 3 datatables should be merged and sum up to derive the opening stock as on given period. 4 th datatable is for Purchases done for the given period. The last one Datatable is for Sales done for the given period.
Here is my question:
How can i merge the 3 datatables and using the first 2 columns and summing the values?
How can i use the tables in crystal reports?
My code is :
Dim con As New ClassConnection
If con.Conn.State = ConnectionState.Closed Then con.Conn.Open()
'To get Opening Stock in Full Quantity
Dim sql As String = "SELECT tblBrand.B_ID AS ID, tblBrand.B_Name AS Brand," & _
" Sum (tblOp_Details.Net_Qty) AS Quantity FROM tblOp_Stock INNER JOIN (tblBrand INNER JOIN" & _
" tblOp_Details ON tblBrand.B_ID = tblOp_Details.B_ID) ON tblOp_Stock.Stk_ID = tblOp_Details.Stk_ID" & _
" WHERE tblOp_Stock.God_ID = #GID GROUP BY tblBrand.B_ID, tblBrand.B_Name"
'To get Purchases < start date and adding to the opening stock
Dim sql1 As String = "SELECT tblBrand.B_ID AS ID, tblBrand.B_Name AS Brand," & _
" Sum (tblPur_Details.Net_Qty) AS Quantity FROM tblPurchase INNER JOIN (tblBrand INNER JOIN" & _
" tblPur_Details ON tblBrand.B_ID = tblPur_Details.B_ID) ON tblPurchase.Pur_ID = tblPur_Details.Pur_ID" & _
" WHERE tblPurchase.God_ID = #GID AND tblPurchase.Rec_Date < #SDate GROUP BY tblBrand.B_ID, tblBrand.B_Name"
'To get Sales < Start date and subtracting to the above
Dim sql2 As String = "SELECT tblBrand.B_ID AS ID, tblBrand.B_Name AS Brand," & _
" Sum (tblSales_Details.Net_Qty) AS Quantity FROM tblSales INNER JOIN (tblBrand INNER JOIN" & _
" tblSales_Details ON tblBrand.B_ID = tblSales_Details.B_ID) ON tblSales.Sale_ID = tblSales_Details.Sale_ID" & _
" WHERE tblSales.God_ID = #GID AND tblSales.Sale_Date < #SDate GROUP BY tblBrand.B_ID, tblBrand.B_Name"
'The above 3 condition is for deriving opening stock as on given date
'To get Purchases >= Start Date and <= Start Date
Dim sql3 As String = "SELECT tblBrand.B_ID AS ID, tblBrand.B_Name AS Brand," & _
" Sum(tblPur_Details.Net_Qty) AS Quantity FROM tblBrand INNER JOIN (tblPurchase INNER JOIN" & _
" tblPur_Details ON tblPurchase.Pur_ID = tblPur_Details.Pur_ID) ON tblBrand.B_ID = tblPur_Details.B_ID" & _
" WHERE tblPurchase.God_ID = #GID And tblPurchase.Rec_Date >= #SDate And tblPurchase.Rec_Date" & _
" <= #EDate GROUP BY tblBrand.B_ID, tblBrand.B_Name"
'The above condition is for deriving Purchases as on given date
'To get Sales >= Start Date and <= Start Date
Dim sql4 As String = "SELECT tblBrand.B_ID AS ID, tblBrand.B_Name AS Brand," & _
" Sum(tblSales_Details.Net_Qty) AS Quantity FROM tblBrand INNER JOIN (tblSales INNER JOIN" & _
" tblSales_Details ON tblSales.Sale_ID = tblSales_Details.Sale_ID) ON tblBrand.B_ID = tblSales_Details.B_ID" & _
" WHERE tblSales.God_ID = #GID And tblSales.Sale_Date >= #SDate And tblSales.Sale_Date <= #EDate" & _
" And tblSales_Details.S_Active = #SAct GROUP BY tblBrand.B_ID, tblBrand.B_Name"
'The above condition is for deriving Sales as on given date
Dim da As New OleDb.OleDbDataAdapter(sql, con.Conn)
Dim da1 As New OleDb.OleDbDataAdapter(sql1, con.Conn)
Dim da2 As New OleDb.OleDbDataAdapter(sql2, con.Conn)
Dim da3 As New OleDb.OleDbDataAdapter(sql3, con.Conn)
Dim da4 As New OleDb.OleDbDataAdapter(sql4, con.Conn)
da.SelectCommand.Parameters.AddWithValue("#GID", Me.stBar_G_ID.Text)
da1.SelectCommand.Parameters.AddWithValue("#GID", Me.stBar_G_ID.Text)
da1.SelectCommand.Parameters.AddWithValue("#SDate", Me.dtpStart.ToString)
da2.SelectCommand.Parameters.AddWithValue("#GID", Me.stBar_G_ID.Text)
da2.SelectCommand.Parameters.AddWithValue("#SDate", Me.dtpStart.ToString)
da3.SelectCommand.Parameters.AddWithValue("#GID", Me.stBar_G_ID.Text)
da3.SelectCommand.Parameters.AddWithValue("#SDate", Me.dtpStart.ToString)
da3.SelectCommand.Parameters.AddWithValue("#EDate", Me.dtpEnd.ToString)
da4.SelectCommand.Parameters.AddWithValue("#GID", Me.stBar_G_ID.Text)
da4.SelectCommand.Parameters.AddWithValue("#SDate", Me.dtpStart.ToString)
da4.SelectCommand.Parameters.AddWithValue("#EDate", Me.dtpEnd.ToString)
da4.SelectCommand.Parameters.AddWithValue("#SAct", "Yes")
Dim dt As New DataTable
Dim dt1 As New DataTable
Dim dt2 As New DataTable
Dim dt3 As New DataTable
Dim dt4 As New DataTable
Ignoring the fact that such operations should be done in the database instead of memory, you can use Linq-To-DataSet which is a subset of Linq-To-Objects.
If you want to concatenate the three tables, group by ID + Brand to get the sum of Quantity:
Dim allRows = dt1.AsEnumerable().Concat(dt2.AsEnumerable()).Concat(dt3.AsEnumerable())
Dim query = From row In allRows
Let GroupColumns = New With {
.Id = row.Field(Of Int32)("Id"),
.Brand = row.Field(Of String)("Brand")
}
Group row By GroupColumns Into Group
Select New With {
.Id = GroupColumns.Id,
.Brand = GroupColumns.Brand,
.SumQuantity = Group.Sum(Function(row) row.Field(Of Int32)("Quantity"))
}
Fill the merged table from the query:
Dim dt As DataTable = dt1.Clone() ' empty, same columns
For Each x In query
Dim row = dt.Rows.Add()
row.SetField("Id", x.Id)
row.SetField("Brand", x.Brand)
row.SetField("Quantity", x.SumQuantity)
Next

Using a SELECT statement to return a row where a DateTime column = variable of type Date?

I am using OleDb, trying to do this:
Dim d as Date = DateSerial(Year(rptDate), Month(rptDate), 1 - 1)
Dim conn as OleDbConnection = new OleDbConnection(connStr)
Dim cm as OleDbCommand = new OleDbCommand()
conn.Open()
cm.Connection = conn
cm.CommandText = "SELECT * FROM history WHERE ReportDate = " & d
Okay, so I know it returns 1 row because I'm staring at it in SQL Server. Here is what I've tried so far for the query in the last line, none work:
"SELECT * FROM history WHERE ReportDate = " & d
"SELECT * FROM history WHERE ReportDate = " & d.toString("G")
"SELECT * FROM history WHERE ReportDate = '" & d & "'"
"SELECT * FROM history WHERE ReportDate = '" & d.toString("G") & "'"
"SELECT * FROM history WHERE ReportDate = '#" & d & "#'"
"SELECT * FROM history WHERE ReportDate = #" & d & "#" 'These last 2 with toString
I have also tried:
cm.CommandText = "SELECT * FROM history WHERE ReportDate = ?"
cm.Parameters.Add(d)
cm.CommandText = "SELECT * FROM history WHERE ReportDate = ?"
cm.Parameters.Add(d.toString("G"))
cm.CommandText = "SELECT * FROM history WHERE ReportDate = '?'"
cm.Parameters.Add(d.toString("G"))
cm.CommandText = "SELECT * FROM history WHERE ReportDate = '?'"
cm.Parameters.Add(d)
Clearly I am missing something here, help? I know that d is the same date as the one in SQL server, specifically 3/31/2011 12:00:00 AM.
Write
cm.CommandText = "SELECT * FROM history WHERE ReportDate = ?"
cm.Parameters.AddWithValue("ParamName", d)
Depending on your provider, you may need to use named parameters:
cm.CommandText = "SELECT * FROM history WHERE ReportDate = #date"
cm.Parameters.AddWithValue("date", d)
Try using another date format in your SQL such as:
Cm.CommandText = "SELECT * FROM history WHERE ReportDate = '" & d.toString("mm/dd/yyyy") & "'"
Did you mean to create your date variable (d) as the day before the rptDate value (ie. with a day of zero (1-1)) ?
This (below) will get you your record (assuming the record has no time part).
SELECT * FROM history WHERE ReportDate = '" & d.toString("dd-MMM-yyyy") & "'"
(The explicit date format is unambiguous, whereas "G" is not.)
...or...
cm.CommandText = "SELECT * FROM history WHERE ReportDate = #date"
cm.Parameters.AddWithValue("#date", d)
Your query as stated is asking "give me all the entries for exactly midnight on this date".
Something like this should hopefully work:
cm.CommandText = "DECLARE #MyDate DATETIME; SET #MyDate = ?; SELECT * FROM history WHERE ReportDate >= #MyDate AND ReportDate < DateAdd(day,1,#MyDate);"
cm.Parameters.Add(d)
This will return all entries on or after midnight of the date and before midnight of the next day.