Sum field in sub query in Linq giving Cannot Assign Method error - linq

I want to be able to group a sub-linq query, but LinqPad is giving an error at this line:
ratetocharge =rtc.rate.Sum
The error is: Cannot assign method group to anonymous type property.
Could anyone advise what I should enter in that line, to give me a sum of the rate within the rates table?
Thank you,
Mark
var mtgRooms = RoomUnit
.Where(r => r.building_id==1)
.GroupBy(p => p.Type)
.Select(g => new
{
TypeName = g.Key.type_name,
TypeID = g.Key.type_id,
TypeCount = g.Count(),
rates = rates
.Select ( rtc =>
new
{
occ = rtc.occ,
ratetocharge =rtc.rate.Sum // this is the line which errors
}
)
.GroupBy(pe => pe.occ)
}
);
mtgRooms.Dump();
EDIT: To add further detail
Tables:
Table RoomUnit
type_id (key - int)
type_name (string - eg. large room, small room, medium room)
building_id (int - denotes a number of buildings this room could be within)
Rates
rate_id
type_id (foreign key to RoomUnit)
occ (type of rate - ie. Desk, FullRoom)
The idea is I want to provide a model that looks like this:
Type of Room
Number of Types of Room available
Type of Occ/Desks available
Sum of Rate (rate to charge) for each type of desk
Currently what shows is:
LargeRoom, Type 3049, Type Count 18 (or whatever is available)
occ FullRoom, ratetocharge 250, numOfOcc 1
occ FullRoom, ratetocharge 250, numOfOcc 1
occ FullRoom, ratetocharge 250, numOfOcc 1
occ Single Desk, ratetocharge 45, numOfOcc 1
occ Single Desk, ratetocharge 45, numOfOcc 1
SmallRoom, Type 3093, Type Count 4 (or whatever is available)
occ FullRoom, ratetocharge 150, numOfOcc 1
occ FullRoom, ratetocharge 150, numOfOcc 1
occ Single Desk, ratetocharge 45, numOfOcc 1
occ Single Desk, ratetocharge 45, numOfOcc 1
occ Single Desk, ratetocharge 45, numOfOcc 1
Whereas I would like the model to sum the rateToCharge by Occ in the sub table, eg:
LargeRoom, Type 3049, Type Count 18 (or whatever is available)
occ FullRoom, ratetocharge 750, numOfOcc 3
occ Single Desk, ratetocharge 90, numOfOcc 2
SmallRoom, Type 3093, Type Count 4 (or whatever is available)
occ FullRoom, ratetocharge 300, numOfOcc 2
occ Single Desk, ratetocharge 135, numOfOcc 3

change ratetocharge =rtc.rate.Sum to ratetocharge =rtc.rate.Sum(). Using Sum the compiler thinks you are trying to make the ratetocharge variable assigned the method group; the set of methods (including overloads) of the Sum method. Instead you need to make the call Sum() which actually calls the method.
--- Edit --- looking at your further information, I am going with this as the way to implement
var mtgRooms = RoomUnit
.Where(r => r.building_id==1)
.GroupBy(p => p.Type)
.Select(g => new
{
TypeName = g.Key.type_name,
TypeID = g.Key.type_id,
TypeCount = g.Count(),
rates = Rates.Where(rt => rt.type_id == g.type_id).GroupBy(rt => rt.occ)
.Select(proj => new {
occ = proj.Key,
ratetocharge = proj.Sum(s => s.rate),
numOfOcc = proj.count())
})
}
);

Related

what to do to make shinyapp give me my output

The primary variable is AgeGroup which has 2 levels. I am trying to get the sample size to output, but for some reason the app either gives error or wont output anything. Can anyone help? The are some comments in the code to help with confusion
Code:
library(shiny)
library(shinyWidgets)
library(survival)
library(shinyjs)
library(survminer)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("ProMBA Haslam Ad Sample Size"),
#Put in all key5 inputs as numeric inputs that the user will type in and choose starting, default values for these inputs
tabPanel("Inputs",
div( id ="form",
column(4,
numericInput("power", label=h6("Power"), value = .9),
numericInput("alpha", label=h6("Alpha"), value = .05),
numericInput("precision", label=h6("Precision"), value =0.05),
numericInput("Delta", label=h6("Delta"), value=.3),
column(4,
numericInput("sample", label=h6("Starting Sample Size"), value = 40),
numericInput("reps", label=h6("Number of Replications"), value=1000)),
),
column(4,
#title of output
h4("Calculated Sample Size"),
verbatimTextOutput(("n"),placeholder=TRUE)),
#create action buttons for users to run the form and to reset the form
textOutput("Sample Size (n)"),
column(4,
actionButton("action","Calculate"))
)))
server = function(input,output,session){
buttonGo = eventReactive(input$action, {withProgress(message = "Running", {
#relist the key inputs and save them to be able to be used in the rest of the code
n<-input$sample/2
alpha<-input$alpha
power <- input$power
beta<-1-input$power
precision<-input$precision
delta <- input$Delta +1
rep <- input$reps
nincrease<-10
#manually5 load in the data from the baseline data .xlxs file
Reporting <- c("12/13/21","12/14/21","12/15/21","12/16/21","12/17/21","12/18/21","12/19/21","12/20/21","12/21/21","12/22/21","12/23/21","12/24/21","12/25/21","12/26/21","12/27/21","12/28/21","12/29/21","12/30/21","12/31/21","1/1/22")
AdSet <- "Status Quo"
Results <- c(70,52, 33, 84, 37, 41, 22, 53, 78, 66, 100, 110, 52, 43, 63, 84, 16, 64, 21, 69)
ResultIndicator <- "actions:link_click"
Budget <- 100
CostPerClick<- c(1.43, 1.92, 3.03, 1.19, 2.70, 2.44, 4.55, 1.89, 1.28, 1.52, 1.00, 0.91, 1.92, 2.33, 1.59, 1.19, 6.25, 1.56, 4.76, 1.45)
Impressions <- c(7020, 8430, 5850, 7920, 6890, 7150, 6150, 7370, 8440, 6590, 6750,8720, 6410,7720, 6940, 8010, 7520, 7190, 6540, 6020)
df <- data.frame(Reporting, AdSet, Results, ResultIndicator,Budget,CostPerClick,Impressions)
#define the standard deviation of the results as well as the mean for group 1 of the 2 level variable and the mean for group 2
mean1 = mean(df$Results)
sd1 = sd(df$Results)
mean2 = delta*mean1
click=rep(0,n)
#Create 2 level variable
AgeGroup <- rep(c("Age21-35","Age36-50"),each=n)
#create new data frame with 2 level variable and click repetitions
DataFrame2 <- data.frame(AgeGroup,click)
#create new data frame binding all of the input variables together
DataFrame3 <- data.frame(cbind(n,alpha,power,precision,delta,rep))
#create for loop to find the pvalue of the ttest run with click~AgeGroup
trials=function(){
for(i in 1:nrow(DataFrame2)){
if(any(DataFrame2$AgeGroup[i]=="Age21-35")){DataFrame2$click[i] =rnorm(1,mean1,sd1)}else{DataFrame2$click[i] =rnorm(1,mean2,sd1)}
}
pvalttest=t.test(click~AgeGroup, data=DataFrame2)
return(pvalttest$p.value)
}
p_values=replicate(200,trials())
p_values=replicate(input$rep,trials())
#find if the p value is significance
significance=p_values[p_values<alpha]
#find the power of the signifiance and the pvalue
power <- length(significance)/length(p_values)
print(c(power,n))
#run a while loop to find the n within the goal power limits
goalpower<-1-beta
lowergoal<-goalpower-input$precision
uppergoal<-goalpower+input$precision
while (power<lowergoal||power>uppergoal){
if (power<lowergoal){
n=n+nincrease
AgeGroup=c()
click=c()
AgeGroup=rep(c("Age21-35","Age36-50"), each=n)
click=rep(NA,2*n)
Dataframe2=data.frame(AgeGroup,click)
p_values=replicate(input$reps, trials())
significance=p_values[p_values<alpha]
power=length(significance)/length(p_values)
print(c(n, power))
}else{
nincrease=nincrease%/%(10/9) #%/% fixes issue of rounding
n=n-nincrease
AgeGroup=c()
click=c()
AgeGroup=rep(c("Age21-35","Age36-50"), each=n)
click=rep(NA,2*n)
DataFrame2=data.frame(AgeGroup,click)
p_values=replicate(input$reps, trials())
significance=p_values[p_values<alpha]
power=length(significance)/length(p_values)
print(c(n, power))
}
}
#n is defined as the sample size of one of the levels of the 2 level variable, so mulitply by 2 to get full sample size
n*2
})
}
shinyApp(ui, server)
i dont need the app to be pretty. I just want it to run whenever someone clicks the calculate button

Laravel Carbon - Calculate time between database entries

I am trying to calculate de difference between two datetimes.
I have two Models, tasks and task_interactions, they are related like this: tasks has many task_interactions, and task_interactions belongs to tasks.
The user can change the status of a task to one of these: "In progress", "Paused" and Finished. The user change the status several times between "In Progress" and "Paused", but once it's finished, the user cannot change the task status anymore.
All interactions are saved in the task_interactions table, with created_by as user_id and created_at as the datetime. the table has these columns: id ; task_id ; status ; comments ; created_by ; created_at.
Here's na exemple for task id = 1:
# id, task_id, status, comments, created_by, created_at
144, 1, In Progress, , 1, 2017-11-14 09:42:20
145, 1, Paused, , 1, 2017-11-14 09:45:53
146, 1, In Progress, , 1, 2017-11-14 09:46:57
147, 1, Paused, , 1, 2017-11-14 09:49:57
148, 1, In Progress, , 1, 2017-11-14 10:00:10
149, 1, Paused, , 1, 2017-11-14 10:06:25
150, 1, In Progress, , 1, 2017-11-14 10:07:26
151, 1, Paused, , 1, 2017-11-14 10:08:11
153, 1, Paused, , 1, 2017-11-14 11:27:04
154, 1, In Progress, , 1, 2017-11-14 11:27:21
155, 1, Paused, , 1, 2017-11-14 11:57:38
The thing is, for me to have the total time spent in one task, i have to determine the time between In Progress and Paused. The time between Paused and In Progress is not relevant.
I am strugling with this. Is there anyone who can help me?
Thanks in advance.
Just one more thing, i am not very experienced, so pardon if my questions sound a bit dummer, I believe that i should do a #foreach loop through all task_interactions where task_id = X, and thats all i know.
As asked, here's the data i am passing for the view:
public function mytasks()
{
$users = User::all();
$mytasks = Task::where('assigned_to','=', Auth::id())->where('status','!=','Finished')->get();
$mytaskscount = Task::where('assigned_to','=', Auth::id())->count();
$tasksinprogress = Task::where('status','=','In Progress')->where('assigned_to','=', Auth::id())->get();
$tasksinprogresscount = Task::where('status','=','In Progress')->where('assigned_to','=', Auth::id())->count();
$taskspaused = Task::where('status','=','Paused')->where('assigned_to','=', Auth::id())->get();
$taskspausedcount = Task::where('status','=','Paused')->where('assigned_to','=', Auth::id())->count();
$tasksfinished = Task::where('status','=','Finished')->where('assigned_to','=', Auth::id())->get();
$tasksfinishedcount = Task::where('status','=','Finished')->where('assigned_to','=', Auth::id())->count();
$tasktypes = Tasktype::all();
$chapters = Chapter::all();
return view('pages.tasks_my', compact('mytasks','tasktypes','chapters','tasksinprogress','taskspaused','tasksfinished','mytaskscount','tasksinprogresscount','taskspausedcount','tasksfinishedcount'));
}
And one more thing, what i know so far
#foreach ($tasks as $task)
#foreach ($task->interactions as $interactions)
{{ In here, every time my loop returns a status = "In progress" i should mark that time, and if that the next loop returns a "Paused", i should count the difference between these two. And sum all other equal cases in the loop. }}
#endforeach
#endforeach
I realy have no idea on how to do that
I would recommend David's answer. If you are not comfortable doing it using MySQL. You may have to do it like this:
Calculate difference between first time a task was started & when it was paused:
$start = Carbon::parse($startTask->created_at);
$pause = Carbon::parse($endTask->created_at);
$diffInSeconds = $pause->diffInSeconds($start)
This should give you the total difference in seconds as to when a tasks was started & then paused. Now you have to repeat this approach for when again a task was started & then paused.
This is strict Mysql, but should do the trick.
You can call this in laravel directly using raw sql instruction, or you should probably rework this into Laravel code.
select SEC_TO_TIME(
sum(
timediff(
if(task_end.created_at is null,
NOW(),
task_end.created_at),
task_start.created_at)))
from task_interactions task_start
left join task_interactions task_end
ON task_end.task_id = task_start.task_id
AND task_end.status IN ('Pause', 'Finished')
AND task_end.created_at = (
SELECT min(created_at)
FROM task_interactions
WHERE status = task_end.status
AND created_at >= task_start.created_at
)
WHERE task_start.task_id = 1
AND task_start.status = 'In Progress'

use for loop to call multiple functions in lua

I want to call multiple methods in lua that are very similar except their parameters change by one character. The way I'm doing it now works but is extremely in efficient.
function scene:createScene(event)
screenGroup = self.view
level1= display.newRoundedRect( 50, 110, 50, 50, 5 )
level1:setFillColor( 100,0,200 )
level2= display.newRoundedRect( 105, 110, 50, 50, 5 )
level2:setFillColor (100,200,0)
--and so on so forth
screenGroup:insert (level1)
screenGroup:insert (level2)
screenGroup:insert (level3)
screenGroup:insert (level4)
end
I plan on extending the screenGroop:insert method to hundreds of levels, maybe up to (level300). As you can see the way I'm doing it now is inefficient. I tried doing
for i=1, 4, 1 do
screenGroup:insert(level..i)
end
but I get the error "table expected."
The best way in this case is to probably use a table:
local levels = {}
levels[1] = display.newRoundedRect( 50, 110, 50, 50, 5 )
levels[1]:setFillColor( 100,0,200 )
levels[2] = display.newRoundedRect( 105, 110, 50, 50, 5 )
levels[2]:setFillColor (100,200,0)
--and so on so forth
for _, level in ipairs(levels) do
screenGroup:insert(level)
end
For other alternatives check the SO answer from #EtanReisner's comment.
If your 'level' tables are global, which is appears they are, you can use getfenv to index them.
for i = 1, number_of_levels do
screenGroup:insert(getfenv()["level" .. i])
end
getfenv returns the environment, with all global variables, in the form of a dictionary. Therefore, you can index it like a normal table like getfenv()["key"]

how to send array of values to a query dynamically in codeigniter

The code in model is
public function get_report6_8($type, $filter_id=NULL) {
$values = array($filter_id);
$select = '';
if ($filter_id && $type == 'jh') {
$select = 'and natbuild_rep.jh_rep_id = ?';
}
else if ($filter_id && $type == 'natbuild') {
$select = 'and natbuild_principal.id = ?';
}
$sql = "select sum(total) total
from (
select value_of_sale total
from lead
left join natbuild_rep
on natbuild_rep.mobile = lead.mobile
left join natbuild_store
on natbuild_store.id = natbuild_rep.store_id
left join natbuild_principal
on natbuild_principal.store_group = ifnull(natbuild_store.store_group2, natbuild_store.store_group)
where (status = 1 OR status = 2)
and value_of_sale is not null
{$select}
group by lead.id
) temp";
return $this->db->query($sql, $values)->row();
}
The code in controller is
$data['report8'] = $this->lead_report_model->get_report6_8($type, $this->input->post('filter'));
code in view is
Grand Total: $total)) ? $report8->total: 0;?>
if I run query like
select sum(total) total
from (
select value_of_sale total
from lead
left join natbuild_rep
on natbuild_rep.mobile = lead.mobile
left join natbuild_store
on natbuild_store.id = natbuild_rep.store_id
left join natbuild_principal
on natbuild_principal.store_group = ifnull(natbuild_store.store_group2, natbuild_store.store_group)
where (status = 1 OR status = 2)
and value_of_sale is not null
and natbuild_principal.id in (18, 30, 31, 35, 33, 25, 23, 15, 8, 6, 5, 29, 7, 3, 2, 1, 24, 27, 22, 21, 20, 26, 36)
group by lead.id ) temp
the result is right. please help how can I send array of values to the $select. This happens when I select grand total from a dropdown which contains all other values up there.
your dropdown is multiselect so it will pass an array with the values.
use
implode(",", $dropdownSelections);
$select = 'and natbuild_principal.id in ('.implode(",", $dropdownSelections).')';

LINQ and 2 datatables

I have 2 datatables in a dataset. One table has a list called CostTypes. Just an Id and Description field.
The other datatable is the master table and has many records and one of the columns is the cost type. There will be cost types that are not reference in this datatable. There is another column in this databale called cost.
What I am trying to do is get a summary by cost type with a total of the cost. But I want ALL cost types listed any values not in the master table will be zero.
CostType table
Id, Description
1,Marketing
2,Sales
3,Production
4,Service
Master table
Id, Cost, CostTypeId
1,10,1
2,120,1
3,40,3
So I would like to see a result in a datable (if possible) so I can bind to datagridview
Marketing 130
Sales 0
Production 40
Service 0
Thanks for the help everyone, this is what I came up from the answers - Can anyone suggest any improvements???
Also how can I convert the result in query1 into a datable???
var query1 =
from rowCT in costTypes.AsEnumerable()
from rowSTD in stdRates.AsEnumerable()
.Where( d => d.Field<int?>( "CostTypeId" ) == rowCT.Field<int?>( "CostTypeId" ) )
.DefaultIfEmpty()
group new { row0 = rowCT, row1 = rowSTD }
by rowCT.Field<string>( "Description" ) into g
select new
{
g.Key,
Cost = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "Cost" ) ),
TotalCost = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "TotalCost" ) ),
TotalHours = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "TotalHours" ) ),
TotalLabourCost = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "TotalLabourCost" ) )
}
;
Maybe something like this:
Test data:
DataTable dt=new DataTable();
dt.Columns.Add("Id",typeof(int));
dt.Columns.Add("Description",typeof(string));
dt.Rows.Add(1,"Marketing");
dt.Rows.Add(2,"Sales");
dt.Rows.Add(3,"Production");
dt.Rows.Add(4,"Service");
DataTable dt2=new DataTable();
dt2.Columns.Add("Id",typeof(int));
dt2.Columns.Add("Cost",typeof(int));
dt2.Columns.Add("CostTypeId",typeof(int));
dt2.Rows.Add(1,10,1);
dt2.Rows.Add(2,120,1);
dt2.Rows.Add(3,40,1);
Linq query
var query=(
from row in dt.AsEnumerable()
from row1 in dt2.AsEnumerable()
.Where (d =>d.Field<int>("Id")==row.Field<int>("Id") )
.DefaultIfEmpty()
group new{row,row1}
by row.Field<string>("Description") into g
select new
{
g.Key,
Cost=g.Sum (x =>x.row1==null?0:x.row1.Field<int>("Cost"))
}
);
Result
Key Cost
Marketing 10
Sales 120
Production 40
Service 0
You can use the Sum extension method to compute the cost. It will return 0 if the collection is empty which is exactly what you want:
var costTypes = new DataTable("CostTypes");
costTypes.Columns.Add("Id", typeof(Int32));
costTypes.Columns.Add("Description", typeof(String));
costTypes.Rows.Add(1, "Marketing");
costTypes.Rows.Add(2, "Sales");
costTypes.Rows.Add(3, "Production");
costTypes.Rows.Add(4, "Service");
var costEntries = new DataTable("CostEntries");
costEntries.Columns.Add("Id", typeof(Int32));
costEntries.Columns.Add("Cost", typeof(Int32));
costEntries.Columns.Add("CostTypeId", typeof(Int32));
costEntries.Rows.Add(1, 10, 1);
costEntries.Rows.Add(2, 120, 1);
costEntries.Rows.Add(3, 40, 3);
var costs = costTypes
.Rows
.Cast<DataRow>()
.Select(
dr => new {
Id = dr.Field<Int32>("Id"),
Description = dr.Field<String>("Description")
}
)
.Select(
ct => new {
ct.Description,
TotalCost = costEntries
.Rows
.Cast<DataRow>()
.Where(ce => ce.Field<Int32>("CostTypeId") == ct.Id)
.Sum(ce => ce.Field<Int32>("Cost"))
}
);
The result is:
Description|TotalCost
-----------+---------
Marketing | 130
Sales | 0
Production | 40
Service | 0
You can create a new DataSet quite simply:
var costsDataTable = new DataTable("Costs");
costsDataTable.Columns.Add("Description", typeof(String));
costsDataTable.Columns.Add("TotalCost", typeof(Int32));
foreach (var cost in costs)
costsDataTable.Rows.Add(cost.Description, cost.TotalCost);
If the linear search performed by the Where in the code above is a concern you can improve the performance by creating a lookup table in advance:
var costEntriesLookup = costEntries
.Rows
.Cast<DataRow>()
.Select(
ce => new {
Cost = ce.Field<Int32>("Cost"),
CostTypeId = ce.Field<Int32>("CostTypeId")
}
)
.ToLookup(ce => ce.CostTypeId, ce => ce.Cost);
var costs = costTypes
.Rows
.Cast<DataRow>()
.Select(
dr => new {
Id = dr.Field<Int32>("Id"),
Description = dr.Field<String>("Description")
}
)
.Select(
ct => new {
ct.Description,
TotalCost = costEntriesLookup.Contains(ct.Id)
? costEntriesLookup[ct.Id].Sum()
: 0
}
);
I came up with a simpler bit of linq than others seemed to use. Thanks to Martin Liversage for the code to create the input data.
var costTypes = new DataTable("CostTypes");
costTypes.Columns.Add("Id", typeof(Int32));
costTypes.Columns.Add("Description", typeof(String));
costTypes.Rows.Add(1, "Marketing");
costTypes.Rows.Add(2, "Sales");
costTypes.Rows.Add(3, "Production");
costTypes.Rows.Add(4, "Service");
var costEntries = new DataTable("CostEntries");
costEntries.Columns.Add("Id", typeof(Int32));
costEntries.Columns.Add("Cost", typeof(Int32));
costEntries.Columns.Add("CostTypeId", typeof(Int32));
costEntries.Rows.Add(1, 10, 1);
costEntries.Rows.Add(2, 120, 1);
costEntries.Rows.Add(3, 40, 3);
var cte = costTypes.Rows.Cast<DataRow>();
var cee = costEntries.Rows.Cast<DataRow>();
var output = cte.Select(
ct => new {
Description = ct["Description"],
Sum = cee.Where(ce=>ce["CostTypeId"].Equals(ct["Id"])).Sum(ce=>(int)ce["Cost"])
}
);
This may lose efficiency on larger tables since each cost type will search the cost entry table whereas using grouping I suspect you only need one pass over the table. Personally I'd prefer the (to my mind) simpler looking code. It will depend on your use case though.

Resources