I have a stored procedure and often that procedure will return multiple rows, for example:
ID Type Price
1234 A 2.260
1234 B 2.690
1234 C 2.990
1234 D 2.690
1234 D 2.790
1234 D 2.650
1234 D 2.680
And I want to output the latest value for each type. In my data reader I have:
While dr.Read
result.price.TypeA= dr("price")
result.price.TypeB= dr("price")
result.price.TypeC= dr("price")
result.price.TypeD= dr("price")
End While
and my query looks like:
select sm_id,
type,
price
from ** WITH (NOLOCK)
where id = #id
order by id desc
I'm not sure how to store all of my results into my object so I can access them in my front end.
This is may be not most performant query but it will do the job as what you described it
select t1.id, t1.t, t1.maxDt, t2.price
from
(select id, [TYPE] t, MAX(ud) maxDt
from dbo.a it
where id =1
group by id, [type]) t1
left join
dbo.a t2 on t1.id = t2.id and t1.t = t2.[type] and t1.maxDt = t2.ud
Now, storing results in object and displaying it
Public Class MyClass
Public Property Id As Integer
Public Property [Type] As String
Public Property [Date] As DateTime
Public Property Price As Decimal
End Class
. . . . .
Dim myList As New List(Of MyClass)()
While dr.Read()
Dim item As New MyClass()
item.Id = dr("id")
item.[Type] = dr("t")
item.[Date] = dr("maxDt")
item.Price = dr("price")
myList.Add(item)
End While
myDataGrid.DataSource = myList
This is what you, approximately, need
Related
I'm using entity Framework 6.
On my database I have these tables :
MasterTable ( Id , name)
Child1 ( ID , name , vl1 , Master_ID)
Child2 ( ID , name , vl2 , MasterID )
Child3 (ID , name , vl3 , Master_ID )
Child3Itm ( ID , name , Child3_ID)
For a given MasterTable item, I want to load with a single Query from database:
All Child1 where vl1 > 5
All Child2 where vl2 > 6
All Child3 where vl3 > 7
And in each Child3 to load all of the Child3Itm content.
I'm using this query:
Dim lst = (From t In context.MasterTable.Where(Function(t1) t1.id = 7)
Select New With {
t,
.chld1 = t.child1s.Where(Function(t21) t21.vl1 >5),
.chld2 = t.child2s.Where(Function(t31) t31.vl2>6 ),
.chld3 = t.child3s.Where(Function(t41) t41.vl3>7).Select(Function(t411) t411.Child3Itms)
}).ToList
The problem is that no Child3 are selected. All others are OK. What can i do? Thanks in advance!
Without seeing your data, it will be tough to diagnose. But since you have access to a debugger, you can do it yourself. With the code below, step over each line and inspect the variables. It should be easy to see where your code is failing
Dim masters = From t In context.MasterTable Where t = 7
Dim child1s = From m In masters Where m.child1s.vl1 > 5
Dim child2s = From m In masters Where m.child2s.vl2 > 6
Dim child3s = From m In masters Where m.child3s.vl3 > 7
Dim child3i = child3s.Child3Itms
Might be a typo in your question. Make sure the condition for the child3s is correct:
t41.vl>7
Should it be this?
t41.vl3 > 7
Dim lst = (From t In context.MasterTable.Where(Function(t1) t1.id = 7)
Select New With {
t,
.chld1 = t.child1s.Where(Function(t21) t21.vl1 >5),
.chld2 = t.child2s.Where(Function(t31) t31.vl2>6 ),
.chld3 = t.child3s.Where(Function(t41) t41.vl3>7),
.chld3itms = t.child3s.Where(Function(t51) t51.vl3>7).Select(Function(t511) t511.Child3Itms)
}).ToList
Dim lst = (From t In context.MasterTable.Where(Function(t1) t1.id = 7)
Select New With {
t,
.chld1 = t.child1s.Where(Function(t21) t21.vl1 >5),
.chld2 = t.child2s.Where(Function(t31) t31.vl2>6 ),
.chld3 = (From t2 in t.child3s.Where(Function(t41) t41.vl3>7)
Select New With {
t2,
.chld3it=t2.Child3Itms
})
}).ToList
This is working too.
If someone can tell me if this answer is better or no compared with the other solution posted by antoni ???
I am trying to find out from my SQL Server 2012 table what the root WorldID is from data that has a parent child relationship (yes, this is for a role playing game system).
The data sample is this:
The query I used to show the the data is:
SELECT
ID
,Name
,WorldID_Orig
,WorldID_From
,(Select Name from REF_World WHERE ID = WorldID_From) as 'WorldFrom_Name'
,WorldID_To
,(Select Name from REF_World WHERE ID = WorldID_To) as 'WorldTo_Name'
,ObjectType
,ObjID_From
,ObjID_To
,(Select Name from REF_Armor WHERE ID = ObjID_To) as 'Obj_Name'
,DateImported
FROM
REF_WorldObjectTrading
WHERE
ID > 3625
AND ObjectType = 'REF_Armor'
AND (Select Name from REF_Armor WHERE ID = ObjID_To) = 'Body: Dimension Shift'
ORDER BY
WorldID_From, ObjID_From
This data is representative of the data I have in my table. What I would like to do is for each row populate the WorldID_Orig with whatever WorldID_From is the first one in the chain. In this case that would be WorldID = 1.
What I'm struggling with is how to find that the root WorldID is 1 from the data if I have the data from, say, the 4th row of results here. I believe it will involve something along these lines ... but I'm not quite getting how to find the root ID.
declare #ParentID int
set #ParentID= 41385 --(select ID
from REF_Armor
where Name = 'Body: Dimension Shift')
;WITH T (Name, WorldFrom, WorldTo, WorldToName, ObjFrom, ObjTo) AS
(
SELECT
Name, WorldID_From, WorldID_To,
(SELECT Name FROM REF_World WHERE ID = WorldID_To) as WorldToName,
ObjID_From, ObjID_To
FROM
REF_WorldObjectTrading
WHERE
ObjID_From = #ParentID
AND ObjectType = 'REF_Armor'
AND ID > 3625
UNION ALL
SELECT
T1.name, T1.WorldID_From, T1.WorldID_To,
(SELECT Name FROM REF_World WHERE ID = WorldID_To) as WorldToName,
t1.ObjID_From, t1.ObjID_To
FROM
REF_WorldObjectTrading T1
INNER JOIN
T ON T1.objID_From = T.ObjFrom
WHERE
T.ObjFrom <> #ParentID
)
select *
from T
order by objTo, WorldFrom
If anyone can help me to nail this down, I'd be very appreciative. I feel I'm close, but I'm just not getting it. Thanks!
The solution to this issue was two fold. First I needed to make sure that when new Things (such as a new Armor in the REF_Armor table) are added that a new row is added to the Tracing table that has the ParentID NULL. That is done as follows:
Dim WorldID_Orig As Integer = MySession.World.ID
Dim Name As String = "Create " & Session("NewItemName")
Dim ObjID_From As Integer = Nothing
Dim ObjectID As Integer = NewItemID
Dim ObjectType As String = "REF_Armor"
Dim WorldID_From As Integer = Nothing
Dim WorldID_To As Integer = Nothing
MySession.EC.WOT_Insert(WorldID_Orig, Name, ObjID_From, ObjectID, ObjectType, WorldID_From, WorldID_To)
This occurs in the following event:
Protected Sub dsDataView_Inserted(sender As Object, e As SqlDataSourceStatusEventArgs) Handles dsDataView.Inserted
The WOT_Insert procedure does the following:
Public Sub WOT_Insert(WorldID_Orig As Integer,
Name As String,
ObjID_From As Integer,
ObjectID As Integer,
ObjectType As String,
WorldID_From As Integer,
WorldID_To As Integer)
Dim wot As New Elthos_ODS.WorldObjectTrading
wot.WorldID_Orig = WorldID_Orig ' -- HERE WE NEED TO QUERY THE DATABASE TO FIND THE ORIGINAL WORLD ID
wot.DateImported = Now
wot.DateModified = Nothing
wot.DateRemoved = Nothing
wot.Name = Name
wot.ObjID_From = ObjID_From
wot.ObjectID = ObjectID
wot.ObjectType = ObjectType
wot.WorldID_From = WorldID_From
wot.WorldID_To = WorldID_To
wot.InsertClassToDB()
End Sub
Lastly the SQL that queries the database is as follows:
ALTER PROCEDURE [dbo].[S_SYS_Admin_WOT_Trace] (
#ObjectID as int,
#ObjectType as varchar(255)
)
AS
;WITH Hierarchy (
WorldID_Orig,
Name,
WorldID_From,
WorldID_To,
ObjID_From,
ObjectID,
Parents)
AS
(
SELECT
WorldID_Orig,
Name,
WorldID_From,
WorldID_To,
ObjID_From,
ObjectID,
CAST('' AS VARCHAR(MAX))
FROM REF_WorldObjectTrading AS FirtGeneration
WHERE
WorldID_From = 0
and WorldID_To = 0
and ObjectType = #ObjectType
and ID > 3625
UNION ALL
SELECT
nextgeneration.WorldID_Orig,
NextGeneration.Name,
NextGeneration.WorldID_From,
NextGeneration.WorldID_To,
nextgeneration.ObjID_From,
NextGeneration.objectID,
CAST(CASE WHEN Parent.Parents = ''
THEN(CAST(NextGeneration.ObjID_From AS VARCHAR(MAX)))
ELSE(Parent.Parents + '.' + CAST(NextGeneration.ObjID_From AS VARCHAR(MAX)))
END AS VARCHAR(MAX))
FROM REF_WorldObjectTrading AS NextGeneration
INNER JOIN Hierarchy AS Parent
ON NextGeneration.objID_From = Parent.ObjectID
WHERE Parent.ObjectID <> #ObjectID
)
SELECT *
FROM Hierarchy
OPTION(MAXRECURSION 32767)
I hope this helps others who may find themselves in a similar situation.
I am trying to convert this query:
select sales.TTL_Sales_Net, sales.TTL_Sales_Target, units.TTL_Units_Net
from epos_Anal_Branch_Sales_Day sales
join epos_PULL_PM_SKU_STATUS till on sales.BRANCH_ID = till.BRANCH_ID
join epos_Anal_Branch_Units_Day units on sales.BRANCH_ID = units.BRANCH_ID
where till.BRANCH_ID = 45 and sales.DATEKEY = 20140725 and units.DATEKEY = 20140725
from SQL into an Entity Framework query in VB.net. I am sending in the BRANCH_ID in my function and producing the datekey like so:
Dim MyDate As String = Date.Now.ToString("yyyyMMdd")
This is what I have but it just returns no results and I am at a complete loss as to why! This is my query thus far, if anyone can spot what I have done wrong then I would be grateful for a push in the right direction
Public Class clsStoreSales
Public Property DailyAmount As String
Public Property DailyUnits As String
Public Property SalesTarget As String
Public Property ErrorMessages As String
Public Shared Function GetStoreSales(ByVal BranchID As String) As List(Of clsStoreSales)
Dim live As New RMISEntitiesLive
Dim MyDate As String = Date.Now.ToString("yyyyMMdd")
Dim l As New List(Of clsStoreSales)
Try
Dim r = From till In live.epos_PULL_PM_SKU_STATUS
Join sales In live.epos_Anal_Branch_Sales_Day On till.BRANCH_ID Equals sales.BRANCH_ID
Join units In live.epos_Anal_Branch_Units_Day On till.BRANCH_ID Equals units.DATEKEY
Where till.BRANCH_ID = CDbl(BranchID) AndAlso sales.DATEKEY = CDbl(MyDate) AndAlso units.DATEKEY = CDbl(MyDate)
Select New With {.SalesAmount = sales.TTL_Sales_Net, .SalesTarget = sales.TTL_Sales_Target, .SaleUnits = units.TTL_Units_Net}
For Each t In r
Dim m As New clsStoreSales
m.DailyAmount = CStr(t.SalesAmount)
m.DailyUnits = CStr(t.SaleUnits)
m.SalesTarget = CStr(t.SalesTarget)
l.Add(m)
Next
Return l
Catch ex As Exception
Dim e As New clsStoreSales
e.ErrorMessages = ex.ToString
l.Add(e)
Return l
End Try
End Function
End Class
This is what sqlServer Profiler is showing as the query being run:
exec sp_executesql N'SELECT
[Extent1].[BRANCH_ID] AS [BRANCH_ID],
[Extent2].[TTL_Sales_Net] AS [TTL_Sales_Net],
[Extent2].[TTL_Sales_Target] AS [TTL_Sales_Target],
[Extent3].[TTL_Units_Net] AS [TTL_Units_Net]
FROM [dbo].[epos_PULL_PM_SKU_STATUS] AS [Extent1]
INNER JOIN [dbo].[epos_Anal_Branch_Sales_Day] AS [Extent2] ON [Extent1].[BRANCH_ID] = [Extent2].[BRANCH_ID]
INNER JOIN [dbo].[epos_Anal_Branch_Units_Day] AS [Extent3] ON [Extent1].[BRANCH_ID] = [Extent3].[DATEKEY]
WHERE ( CAST( [Extent1].[BRANCH_ID] AS float) = #p__linq__0) AND ( CAST( [Extent2].[DATEKEY] AS float) = #p__linq__1) AND ( CAST( [Extent3].[DATEKEY] AS float) = #p__linq__2)',N'#p__linq__0 float,#p__linq__1 float,#p__linq__2 float',#p__linq__0=45,#p__linq__1=20140725,#p__linq__2=20140725
This
Join units In live.epos_Anal_Branch_Units_Day On till.BRANCH_ID Equals units.DATEKEY
Should be this!
Join units In live.epos_Anal_Branch_Units_Day On till.BRANCH_ID Equals units.BRANCH_ID
Given a table of thousands of rows of data as shown in the sample below
Id Date SymbolId NumOccs HighProjection LowProjection ProjectionTypeId
1 2014-04-09 28 45 1.0765 1.0519 1
2 2014-04-10 5 44 60.23 58.03 1
3 2014-04-11 29 77 1.026 1.0153 1
and a Class defined as
Public Class ProjectionPerformance
Public symbolId As Integer
Public Name as String
Public Date as String
Public ActualRange as Decimal
End Class
I am trying to return the following for each symbolId;
The symbolId (from this table)
The symbol Name (from the symbols table)
The Actual Range (High Projection - Low Projection)
Can this be done in one query since i am essentially in need of a Dictionary(Of Integer, List(Of ProjectionPerformance)) where the integer is the symbolId and the List is generated from the query?
Updated:
So as to be a little clearer, Here is what I'm doing so far but contains two LINQ iterations
Public Shared Function GetRangeProjectionPerformance(Optional daysToRetrieve As Integer = 100) As Dictionary(Of Integer, List(Of ProjectionPerformance))
Dim todaysDate As Date = DateTime.Now.Date
Dim lookbackDate As Date = todaysDate.AddDays(daysToRetrieve * -1)
Dim temp As New Dictionary(Of Integer, List(Of ProjectionPerformance))
Using ctx As New ProjectionsEntities()
Dim query = (From d In ctx.projections
Where d.SymbolId <= 42 AndAlso d.Date >= lookbackDate
Join t In ctx.symbols On d.SymbolId Equals t.Id
Let actualRange = d.HighProjection - d.LowProjection
Select New With {
d.Date,
d.SymbolId,
t.Name,
actualRange}).GroupBy(Function(o) o.SymbolId).ToDictionary(Function(p) p.Key)
For Each itm In query
Dim rpp As New ProjectionPerformance
Dim rppList As New List(Of ProjectionPerformance)
If itm.Value.Count > 0 Then
For x As Integer = 0 To itm.Value.Count - 1
Dim bb As Integer = Convert.ToInt32(itm.Value(x).SymbolId)
With rpp
.SymbolId = bb
.ProjectionDate = itm.Value(x).Date.ToString()
.Name = itm.Value(x).Name
.ProjectedRange = itm.Value(x).actualRange
End With
rppList.Add(rpp)
Next
End If
temp.Add(itm.Key, rppList)
Next
End Using
Return temp
End Function
I'm going to answer in C#, but I think you'll get the gist of it anyway. Basically, you can group by SymbolId, build your object graph and then use ToDictionary using the Key to create dictionary.
var result = (From d In _projectionEntities.projections
Where d.SymbolId <= 42
group d by d.SymbolId into g
select new {
SymbolId = g.Key,
ProjectionPerformances =
g.Select(gg=>new ProjectionPerformance{
SymbolId = gg.SymbolId,
Name = gg.Symbol.Name,
rpDate = gg.Date.ToString(),
ActualRange = gg.HighProjection - gg.LowProjection
})
.ToDictionary(g=>g.SymbolId);
Try
Dim Result = (From d In _ProjectionEntities.projections
Join t In _projectionEntities.symbols On d.SymbolId Equals t.Id
Where d.SymbolId <= 42
Select New With {.SymbolID = d.SymbolID
.Date = d.Date
.Name = t.Name
.ActualRange = d.HighProjection - d.LowProjection})
I have created the Datatable below which feeds a GridView on Page_Load
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim strQuery As String = "SELECT DISTINCT setsTbl.setName, trainingTbl.t_date, userAssessmentTbl.o_id FROM userAssessmentTbl LEFT JOIN trainingTbl ON userAssessmentTbl.tt_id = trainingTbl.tt_id LEFT JOIN setsTbl ON trainingTbl.s_id = setsTbl.s_id LEFT JOIN outcomesTbl ON userAssessmentTbl.o_id = outcomesTbl.o_id WHERE UserId = #UserId ORDER BY setName, t_date DESC "
Dim cmd As New SqlCommand(strQuery)
cmd.Parameters.AddWithValue("#UserId", userString)
Dim dt As DataTable = GetData(cmd)
GridView1.DataSource = dt
GridView1.DataBind()
End Sub
At present it outputs values:
SetName t_date o_id
name1 12.12.12 1
name2 13.07.12 1
name2 15.07.12 2
name3 16.07.12 4
name3 17.07.12 3
I would like to get my DataTable below to output distinct rows like this:
SetName t_date o_id
name1 12.12.12 1
name2 13.07.12 1
name3 16.07.12 4
can anybody tell me hw this can be achieved?
It looks like you want the earliest date for each name. If so, you could use a Group By and the min function:
setsTbl.setName, Min(trainingTbl.t_date), Min(outcomesTbl.o_id)
FROM userAssessmentTbl LEFT JOIN trainingTbl ON userAssessmentTbl.tt_id = trainingTbl.tt_id
LEFT JOIN setsTbl ON trainingTbl.s_id = setsTbl.s_id LEFT JOIN outcomesTbl
ON userAssessmentTbl.o_id = outcomesTbl.o_id
WHERE UserId = #UserId Group By setsTbl.setName ORDER BY setsTbl.setName