Does linq to sql have a with ties option? - linq-to-sql

I'm trying to move the following query to Linq-to-sql, is it possible?
select * from (
Select top (#Percent) percent with ties *
from(
Select distinct
LoanNumber as LoanNo
From CHE
Left Join RecordingInfo as Rec
On CHE.LoanNumber = Rec.LoanNo
Where Channel = 'LINX'
and CHE.Doc in ('MTG','MOD')
and Rec.LoanNo is null
and LoanNumber >= '#LoanNo'
) A
order by LoanNo #Order
) B
order by LoanNo
I have not seen anyway to do with ties in linq.

I think something like this will work for you.
public static IQueryable<T> TopPercentWithTies<T, TKey>(this IOrderedQueryable<T> query, Expression<Func<T, TKey>> groupByExpression, double percent)
{
var groupedQuery = query.GroupBy(groupByExpression);
int numberToTake = groupedQuery.Count() * percent / 100;
return groupedQuery.Take(numberToTake).SelectMany(t => t);
}
I only tested it with IEnumerable, so I don't know for sure that it'll work properly with IQueryable. I also sorted the list before calling TopPercentWithTies().
Here's the code I used to test it.
int percent = 50;
var people = new []
{
new { Age = 99, Name = "Adam" },
new { Age = 99, Name = "Andrew" },
new { Age = 89, Name = "Bob" },
new { Age = 50, Name = "Cecil" },
new { Age = 50, Name = "Doug" },
new { Age = 50, Name = "Everett" },
new { Age = 35, Name = "Frank" },
new { Age = 25, Name = "Greg" },
new { Age = 15, Name = "Hank" }
};
var sortedPeople = people.AsQueryable().OrderByDescending(person => person.Age);
var results = sortedPeople.TopPercentWithTies(person => person.Age, percent);
foreach (var person in results)
Console.WriteLine(person);
Hope it helps or at least gets you in the right direction. You may want to tweak the logic for calculating numberToTake.

Related

Server side pagination in Graphql Scala

I need to do server side pagination in graphql in scala. I have seven reports and have used one graphql query with different operations to get the data. Now I need to add server side pagination to it and I am not able to do that. Any help would be appreciated. Below are my code:
Schema:
val PanelNominationStatusReportDataType = ObjectType(
"PanelNominationStatus",
"Dashboard Reports",
fields[Unit, PanelRewardSatusDetail](
Field("awardName", OptionType(StringType), resolve = _.value.awardName),
Field("nominatorEmail", OptionType(StringType), resolve = _.value.nominatorEmail),
Field("nomineeEmail", OptionType(StringType), resolve = _.value.nomineeEmail),
Field("nomineeLocation", OptionType(StringType), resolve = _.value.nomineeLocation),
Field("approverEmail", OptionType(StringType), resolve = _.value.approverEmail),
Field("citation", OptionType(StringType), resolve = _.value.citation),
Field("businessJustification", OptionType(StringType), resolve = _.value.businessJustification),
Field("rating", OptionType(IntType), resolve = _.value.rating),
Field("votingStatus", OptionType(StringType), resolve = _.value.votingStatus),
Field("nominatedDate", OptionType(StringType), resolve = _.value.nominatedDate),
Field("approvedDate", OptionType(StringType), resolve = _.value.approvedDate)
)
)
Graphql Query:
Field(
"PanelNominationStatus",
ListType(PanelNominationStatusReportDataType),
description = Some("Returns the Employee Reward Report Data"),
arguments = companyIdType :: rewardNamesType :: startDateType :: endDateType :: Nil,
resolve = { c =>
c.ctx.getPanelStatusReport(c.arg(companyIdType), c.arg(startDateType), c.arg(endDateType), c.arg(rewardNamesType))
})
DataRepo:
def getPanelStatusReport(companyId: Int, startDate: Long, endDate: Long, rewardNames: Seq[String]): List[PanelRewardSatusDetail] = {
val redemptionReport = Await.result(reportsModel.findPanelRewardStatusDetailsReport(companyId, rewardNames, startDate, endDate), 20.seconds).toList
redemptionReport
}
And at last the model:
def findPanelRewardStatusDetailsReport(companyId: Int, rewardNames: Seq[String], startDate: Long, endDate: Long): Future[Seq[PanelRewardSatusDetail]] = {
val df = new SimpleDateFormat("dd-MM-yyyy")
val start = stringToDateTime(df.format(startDate * 1000L), None).toDateTime()
val end = stringToDateTime(df.format(endDate * 1000L), None).toDateTime()
val rewardFilter = if(rewardNames.nonEmpty) "AND vrrc.reward_name IN (" + rewardNames.map(a => "'" + a + "'").mkString(",") + ")" else ""
implicit val getOrdersResult = GetResult(r => PanelRewardSatusDetail(r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<))
val q = sql"""select vrrc.reward_name, (select login from users where id=vrur.sender_id), (select login from users where id=vrur.receiver_ids), (select city_name from cities where id=(select city_id from users where id=vrur.receiver_ids)), (select login from users where id=approver_user_id), vrur.comment, vrur.business_justification, vrpa.rating, CASE WHEN vrpa.is_approved = 1 THEN 'VOTED' ELSE 'NOT VOTED' END, date(vrpa.created_at), date(vrpa.approved_at) from vr_panel_approval vrpa inner join vr_user_reward vrur on vrur.id=vrpa.user_reward_id inner join vr_reward_config vrrc on vrrc.id=vrur.reward_config_id where vrrc.company_id = $companyId and date(vrpa.created_at) between date($start) and date($end) #$rewardFilter"""
db.run(q.as[PanelRewardSatusDetail])
}
My request query:
{
"query": "query PanelNominationStatus($startDate: Long!, $endDate: Long!, $companyId: Int!, $rewardNames: [String!]!) { PanelNominationStatus( startDate: $startDate, endDate: $endDate, companyId: $companyId, rewardNames: $rewardNames ) { awardName nominatorEmail nomineeEmail nomineeLocation approverEmail citation businessJustification rating votingStatus nominatedDate approvedDate }}",
"operationName": "PanelNominationStatus",
"variables": {
"startDate": 1285891200,
"endDate": 1576108800,
"companyId": 355,
"rewardNames": ["PANEL AWARD FEBRUARY", "PANEL AWARD MARCH"]
}
}
I can make it possible using limit in the query and accepting it in the query but I need to send the total count of rows in the response as well. But I am not able to figure out where to make change in schema.
You just need to define another GraphQL type for your result which also contains the count,
val PanelNominationStatusResultType = ObjectType(
"PanelNominationStatusResult",
"Dashboard Reports",
fields[Unit, List[PanelRewardSatusDetail]](
Field(
"count",
IntType,
description = Some("count of nomination-status-reports in this response"),
resolve = _.value.length
),
Field(
"panelNominationStatusList",
ListType(PanelNominationStatusReportDataType),
description = Some("list of nomination-status-reports"),
resolve = _.value
)
)
)
Now, as for your query,
Field(
"panelNominationStatusResult",
PanelNominationStatusResultType,
description = Some("Returns the details of ............"),
arguments = companyIdType :: rewardNamesType :: startDateType :: endDateType :: Nil,
resolve = { c =>
c.ctx.getPanelStatusReport(c.arg(companyIdType), c.arg(startDateType), c.arg(endDateType), c.arg(rewardNamesType))
}
)
If you want the totalCount, then first of all you need to change your getPanelStatusReport method to also return the totalCount
def findPanelRewardStatusDetailsReport(
companyId: Int,
rewardNames: Seq[String],
startDate: Long,
endDate: Long
): Future[(Int, Seq[PanelRewardSatusDetail])] = ???
// updated result type
val PanelNominationStatusResultType = ObjectType(
"PanelNominationStatusResult",
"Dashboard Reports",
fields[Unit, (Int, List[PanelRewardSatusDetail])](
Field(
"totalCount",
IntType,
description = Some("total count of nomination-status-reports"),
resolve = _.value._1
),
Field(
"count",
IntType,
description = Some("count of nomination-status-reports in this response"),
resolve = _.value._2.length
),
Field(
"panelNominationStatusList",
ListType(PanelNominationStatusReportDataType),
description = Some("list of nomination-status-reports"),
resolve = _.value._2
)
)
)

Laravel How Make DB raw can inside funtion

I have problem on laravel. I want to showing percentage on with eloquent, but return null value
This Is My Controller
$group_categories = Proyek::with(['modul' => function($query){
$query->select(DB::raw('((select count(*) from modul where status = 0 and deleted_at IS NULL) /
(select count(*) from modul where deleted_at IS NULL)) *
100 as count' ));
}])->get();
This Is Json return
{
id: "10",
proyek: "JuZka",
created_at: "2018-08-12 01:54:04",
updated_at: "2018-09-23 05:49:13",
modul: [ ]
},
You can use code like this:
$all_models = (new Proyek)->count();
$models = (new Proyek)->where('status', 0)->count();
$percentage = $models / $all_models * 100;
$group_categories = Proyek::wheere('modul', $percentage);

Contenent is not showing under auto complete text box

I am implementing auto-compete textbox using MVC 4. According to the requirement the textbox can take multiple names(here EmployeeName) separated by "," (comma). I have written the following code for the controller:
public JsonResult EmployeeList(string strEmpName)
{
List<string> list = strEmpName.Split(',').ToList();
list = list.Select(s => s.Trim()).ToList();
//Extract the term to be searched from the list
string searchTerm = list.LastOrDefault().ToString().Trim();
//Return if Search Term is empty
if (string.IsNullOrEmpty(searchTerm))
{
//return new string[0];
}
List<string> excludeEmployeeName = new List<string>();
if (list.Count > 1)
{
list.RemoveAt(list.Count - 1);
excludeEmployeeName = list;
}
var query = (EmployeeDAL.GetEmployee().Where(x => x.EmployeeName.StartsWith(searchTerm.ToString().ToUpper()))).ToList();
var myList = new List<string>();
foreach (var emp in query.ToList())
{
myList.Add(emp.EmployeeName.ToString());
}
return Json(myList, JsonRequestBehavior.AllowGet);
}
The above function is returning JSON.
Data is like:
public class EmployeeDAL
{
public static List<Employee> GetEmployee()
{
var empList = new List<Employee>
{
new Employee { EmployeeId = "E001", EmployeeName = "Alex", DepartmentId = 1 },
new Employee { EmployeeId = "E002", EmployeeName = "Alan", DepartmentId = 2 },
new Employee { EmployeeId = "E003", EmployeeName = "Johny", DepartmentId = 3 },
new Employee { EmployeeId = "E004", EmployeeName = "Joe", DepartmentId = 1 },
new Employee { EmployeeId = "E005", EmployeeName = "Thomas", DepartmentId = 3 },
new Employee { EmployeeId = "E006", EmployeeName = "Sarah", DepartmentId = 3 },
new Employee { EmployeeId = "E007", EmployeeName = "Rahul", DepartmentId = 4 },
new Employee { EmployeeId = "E008", EmployeeName = "Raman", DepartmentId = 1 },
new Employee { EmployeeId = "E009", EmployeeName = "Mandy", DepartmentId = 2 },
new Employee { EmployeeId = "E010", EmployeeName = "Rohit", DepartmentId = 4 },
new Employee { EmployeeId = "E011", EmployeeName = "Sanjay", DepartmentId = 1 },
new Employee { EmployeeId = "E012", EmployeeName = "Abhi", DepartmentId = 3 },
new Employee { EmployeeId = "E013", EmployeeName = "Martin", DepartmentId = 1 },
new Employee { EmployeeId = "E014", EmployeeName = "Robin", DepartmentId = 2 },
new Employee { EmployeeId = "E015", EmployeeName = "Rohit", DepartmentId = 1 },
new Employee { EmployeeId = "E016", EmployeeName = "William", DepartmentId = 3 },
new Employee { EmployeeId = "E017", EmployeeName = "Sourav", DepartmentId = 2 },
new Employee { EmployeeId = "E018", EmployeeName = "Alex", DepartmentId = 2 },
};
return empList.ToList();
}
}
In view I have written the following script:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js"></script>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="Stylesheet" type="text/css" />
<script type="text/javascript">
$(document).ready(function() {
SearchText();
});
function SearchText() {
$("#txtEmployeeName").autocomplete({
source: function(request, response) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "Employee/EmployeeList",
data: "{'strEmpName':'" + extractLast(request.term) + "'}",
dataType: "json",
success: function(data) {
response(data.d);
},
error: function(result) {
alert(result.responseText);
}
});
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function(event, ui) {
var terms = split(this.value);
// remove the current input
terms.pop();
// add the selected item
terms.push(ui.item.value);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
return false;
}
});
$("#txtEmployeeName").bind("keydown", function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).data("autocomplete").menu.active) {
event.preventDefault();
}
})
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
}
</script>
When I run the application and debug the json script using firebug, I can see the data is coming rightly according the letter I type in the text box (txtEmployeeName) but is not showing in the browser window. I have given the total script so that any one can run it.
Any help will be thankfully accepted.

Using Linq to shape structure for Json serialization

I have a pretty simple structure that looks something like this:
var list = new List<CategoryInTimeItem>
{
new CategoryInTimeItem { Name = "Food", Year = 2012, Month = 1, Amount = 100 },
new CategoryInTimeItem { Name = "Food", Year = 2012, Month = 2, Amount = 110 },
new CategoryInTimeItem { Name = "Food", Year = 2012, Month = 3, Amount = 130 },
new CategoryInTimeItem { Name = "Food", Year = 2012, Month = 4, Amount = 130 },
new CategoryInTimeItem { Name = "Transport", Year = 2012, Month = 1, Amount = 1000 },
new CategoryInTimeItem { Name = "Transport", Year = 2012, Month = 2, Amount = 1101 },
new CategoryInTimeItem { Name = "Transport", Year = 2012, Month = 3, Amount = 1301 },
new CategoryInTimeItem { Name = "Transport", Year = 2012, Month = 4, Amount = 1301 }
};
I want to reshape this structure so that when it get's serialized to json the result should look like this, one array for each name:
[
[["2012-1", 100], ["2012-2", 110], ["2012-3", 130], ["2012-4", 130]],
[["2012-1", 1000], ["2012-2", 1101], ["2012-3", 1301], ["2012-4", 1301]]
]
My linq query looks like this:
result.Values =
from d in list
orderby d.Name , d.Year , d.Month
group d by d.Name
into grp
select new[]
{
grp.Select(y => new object[] {y.DateName, y.Amount})
};
This almost works, however I get an extra "level" of arrays, so when serialized to json the result looks like this:
[
[[["2012-1", 100], ["2012-2", 110], ["2012-3", 130], ["2012-4", 130]]],
[[["2012-1", 1000], ["2012-2", 1101], ["2012-3", 1301], ["2012-4", 1301]]]
]
What am I doing wrong here?
You've almost been there, just instead of
from d in list
...
select new[]
{
grp.Select(y => new object[] {y.DateName, y.Amount})
}
simply:
from d in list
...
select grp.Select(y => new object[] {y.DateName, y.Amount}).ToList()
You just added an unnecessary level of array at the end.

LINQ-to-SQL GroupBy across Many-to-Many Divide

I have the following issue to solve.
I have an IQueryable list of Invoices, each tied to an Account. Each Account can have multiple Structures, and Accounts and Structures are tied together by a table called StructureAccount. It looks like this:
Invoice ---> Account <-----StructureAccount ----> Structure
I want to query my IQueryable list of Invoices and group by Structure.StructureID or StructureAccount.StructureID. But, because any given invoice can be tied to multiple Structures the best I can get is a LIST of StructureIDs, and therefore my GroupBy is not working.
I feel like I am missing an obvious solution to this.
I should note that I understand that the data in any one Invoice would be counted multiple times if the Invoice were tied to more than one Structure, and this is "solved" by a "PercentAllocationtoStructure" value in the table StructureAccount.
I hope I did a good enough job explaining this problem. Let me know if not.
Hmmm...I might be missing something, but doesn't the following work?
var q = from i in Invoice
join a in Account
on i.AccountID equals a.AccountID
join sa in StructureAccount
on i.AccountID equals sa.AccountID
join s in Structure
on sa.StructureID equals s.StructureID
group i by s.StructureID;
I tested it on the following dummy data:
var Invoice = new [] {
new { InvoiceID = 1, AccountID = 1 },
new { InvoiceID = 2, AccountID = 2 },
new { InvoiceID = 3, AccountID = 3 },
new { InvoiceID = 4, AccountID = 1 },
new { InvoiceID = 5, AccountID = 2 },
new { InvoiceID = 6, AccountID = 3 }
};
var Account = new [] {
new { AccountID = 1 },
new { AccountID = 2 },
new { AccountID = 3 },
};
var StructureAccount = new [] {
new { AccountID = 1, StructureID = 2 },
new { AccountID = 1, StructureID = 3 },
new { AccountID = 2, StructureID = 2 },
new { AccountID = 3, StructureID = 1 },
new { AccountID = 3, StructureID = 2 },
};
var Structure = new [] {
new { StructureID = 1 },
new { StructureID = 2 },
new { StructureID = 3 }
};
And it returns:
StructureID = 2:
InvoiceID's: 1,2,3,4,5,6
StructureID = 3:
InvoiceID's: 1,4
StructureID = 1:
InvoiceID's: 3,6
I'll assume you have the following starting point:
IQueryable<Invoice> _invoices;
First, you need to get a list of all the items that you will be iterating over:
IQueryable<Account> _accounts = _invoices.Select(myInvoice => myInvoice.Account).Distinct();
IQueryable<StructuredAccount> _structuredAccounts = _accounts.SelectMany(myAccount => myAccount.StructuredAccounts);
IQueryable<Structure> _structures = _structuredAccounts.Select(myStructuredAccount => myStructuredAccount.Structure).Distinct();
Next, you need to go back and join your Structure objects to the respective Invoice objects.
For this, you'll:
Get a set of {Structure, Account} pairs:
var structureAccountJoin = _structures.Join(_structuredAccounts, _structure => structure.StructuredID, _structuredAccount => _structuredAccount.StructuredID, (structure, structuredAccount) => new { Structure = structure, Account = structuredAccount.Account });
Get a set of {Structure, Invoice} pairs:
var structureInvoiceJoin = structureAccountJoin.Join(_invoices, myObj => myObj.Account.AccountID, invoice => invoice.AccountID, (myObj, invoice) => new { Structure = myObj.Structure, Invoice = invoice});
Finally, you can group everything by the Structure object:
IQueryable<IGrouping<Structure, Invoice>> groupByStructure = structureInvoiceJoin.GroupBy(obj => obj.Structure, result => result.Invoice);
(GroupBy documentation: http://msdn.microsoft.com/en-us/library/bb534304.aspx)
Now, you can access everything as follows:
foreach(IGrouping<Structure, Invoice> groupEntry in groupByStructure)
{
Structure currentGrouping = groupEntry.Key;
foreach(Invoice inv in groupEntry)
{
// do something;
}
}
As a note, this is a very complex script that requires a lot of steps if you don't have access to the tables directly. You may want to look into creating a StoredProcedure for this instead, as it will be more efficient and you'll be able to use SQL Joins instead. If you have only an IQueryable<Invoice> to work with and access to nothing else, there is probably a design problem somewhere in your architecture.
Nevertheless, this is the way to make it work based on your requirements, if I read them correctly.