Count Total issued per month using LINQ - sql

I'm doing a sample project where it counts the total issues per month that is to be displayed in a bar graph..
Here is my working SQL query
SELECT
SUM(CASE datepart(month,D_ISSUE) WHEN 1 THEN 1 ELSE 0 END) AS 'Jan',
SUM(CASE datepart(month,D_ISSUE) WHEN 2 THEN 1 ELSE 0 END) AS 'Feb',
so on...
FROM EMP_MEMOS
Can someone help me transpose this SQL Query into a LinQ code. i'm still trying to understand how it works
Here is my code so far, but i still can't get it to work.
public ActionResult MonthCount()
{
var Monthly = (from f in db.EMP_MEMOS
group f by new { month = f.D_ISSUE, year = f.D_ISSUE } into g
orderby g.Key.year
select new
{
dt = string.Format("{0}/{1}", g.Key.month, g.Key.year),
}).ToList();
return Json(new { result = Monthly }, JsonRequestBehavior.AllowGet);
}

I already got the answer, gonna share it here:
public ActionResult CountMonth()
{
var memo = from t in db.EMP_MEMOS
select new
{
t.D_ISSUE.Value.Month,
t.D_ISSUE.Value.Year
};
var res = from s in memo
group s by new { s.Year, s.Month } into g
select new
{
Period = g.Key,
MemoCount = g.Count(),
};
return Json(new { result = res }, JsonRequestBehavior.AllowGet);
}

Related

Convert SQL Query to query in C#

I've currently got the SQL code below:
WITH region_list
AS (SELECT r.StateProvinceRegion,
r.CafeId,
s.Longitude,
s.Latitude,
ROW_NUMBER() OVER(PARTITION BY r.StateProvinceRegion
ORDER BY s.Longitude DESC) AS row_no
FROM CafeAddress r
inner join Restaurant s on s.CafeId = r.CafeId
)
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS ID,
StateProvinceRegion,
Longitude,
Latitude
FROM region_list
WHERE row_no = 1;
How would I go about adding this query? In my method below I've implemented something similar but I don't understand how to add the WITH clause in.
public VersionResponse GetCafeRegion()
{
var regionList = from cafeAddress in _context.CafeAddress
join cafe in _context.Cafe on cafeAddress.CafeId equals cafe.CafeId
select new { cafeAddress.StateProvinceRegion, cafeAddress.CafeId, cafe.Longitude, cafe.Latitude };
return new VersionResponse()
{
Data = regionList
};
}
Try the below code once.
public VersionResponse GetCafeRegion()
{
var CafeAddress = new List<CafeAddress>();
var Cafe = new List<Cafe>();
var regionList = from cafeAddress in _context.CafeAddress
join cafe in _context.Cafe on cafeAddress.CafeId equals cafe.CafeId
group new { cafeAddress.StateProvinceRegion, cafeAddress.CafeId, cafe.Longitude, cafe.Latitude } by cafeAddress.StateProvinceRegion into g
select g;
List<object> finalResult = new List<object>();
int index = 1;
foreach(var gg in regionList)
{
var groupRecord = gg.OrderByDescending(x => x.Longitude).FirstOrDefault();
finalResult.Add(new
{
ID = index++,
groupRecord.StateProvinceRegion,
groupRecord.CafeId,
groupRecord.Latitude,
groupRecord.Longitude
});
}
return new VersionResponse()
{
Data = finalResult
};
}

datediff with case statement in select query linq

select case statement in linq query.
Here is the query on sql:
select case when DATEDIFF(day,convert(varchar,Min([Order].CreatedOnUtc),101),convert(varchar,Max([Order].CreatedOnUtc),101)) = 0 then
Sum([Order].OrderSubtotal)
else
case when (DATEDIFF(day,convert(varchar,Min([Order].CreatedOnUtc),101),convert(varchar,Max([Order].CreatedOnUtc),101))/30) = 0 then Sum([Order].OrderSubtotal) else
Sum([Order].OrderSubtotal)/
(DATEDIFF(day,convert(varchar,Min([Order].CreatedOnUtc),101),convert(varchar,Max([Order].CreatedOnUtc),101))/30)
end
end as 'Account Value' from [order] where And Account.ID = #Act_ID
I am trying the code here:
var query = _orderRepository.Table;
query = query.Where(o => o.AccountId == accountId);
In query i am getting my value.
After query statement what should i write??
how do i write for case statement using linq???
#Manoj, may be the below code helps you. This sample C# project may solve the problem you have.
using System;
using System.Collections.Generic;
using System.Linq;
namespace DateDiffIssue
{
class Program
{
static void Main(string[] args)
{
// Preparing data
var data = new Order[] {
new Order { AccountID = 1, CreatedOnUtc = DateTime.Parse("1.01.2017 10:00"), OrderSubtotal = 100 },
new Order { AccountID = 1, CreatedOnUtc = DateTime.Parse("1.01.2017 12:00"), OrderSubtotal = 150 },
new Order { AccountID = 1, CreatedOnUtc = DateTime.Parse("1.01.2017 14:00"), OrderSubtotal = 150 }
};
// Selection
var selected = (from item in data
let accountData = data.Where(w => w.AccountID == 1)
let minDate = accountData.Min(m => m.CreatedOnUtc).Date
let maxDate = accountData.Where(w => w.AccountID == 1).Max(m => m.CreatedOnUtc).Date
let isSameDate = minDate == maxDate
let basedOn30Days = (maxDate - minDate).TotalDays / 30
let isInside30Days = (int)basedOn30Days == 0
let accountDataSum = accountData.Sum(s => s.OrderSubtotal)
select new
{
AccountValue = isSameDate ? accountDataSum :
isInside30Days ? accountDataSum :
accountDataSum / basedOn30Days
}).Distinct();
// Print each order
selected.ToList().ForEach(Console.WriteLine);
// Wait for key
Console.WriteLine("Please press key");
Console.ReadKey();
}
}
internal class Order
{
public int AccountID { get; set; }
public DateTime CreatedOnUtc { get; set; }
public int OrderSubtotal { get; set; }
}
}

asp.net mvc , raw sql : Display data in Views generated using aggregate function

I am using ASP.NET MVC, EF 6 and SQL Server 2008.
I want to generate a view which would show sum of all the sales in each day for a particular month in a particular year.
I found LINQ query very complicated in such type of job, So I used a raw SQL query. I wrote query and tested in SQL server and it worked fine.
select
YEAR(Date) as Year,
MONTH(Date) as month,
DAY(Date) as date,
SUM(GrandTotal) as Total
from
Sales
where
Year(Date) = 2014
and MONTH(Date) = 12
group by
DAY(Date), YEAR(Date), MONTH(date)
Result
Well currently I don't have much data. But it looks like I got what I wanted from a query.
I wrote a controller for this purpose and now I have no idea how to display this data in View.
public ActionResult MonthlySalesByDate()
{
DateTime today = DateTime.Now.Date;
int _year = today.Year;
int _month = today.Month;
//raw sql query
string query = "select SUM(GrandTotal) as Total, DAY(Date) as date, MONTH(Date) as month, YEAR(Date) as Year from Sales where Year(Date) = " + _year + " and MONTH(Date) =" + _month + " Group by DAY(Date), YEAR(Date), MONTH(date)";
//executing raw sql query
var _model = db.Stocks.SqlQuery(query).ToList();
return View(_model);
}
Please help me out with this. If there is better way of doing this or if I am making mistakes, please let me know.
Start by creating view models to represent what you want to display in the view
public class DayTotalVM
{
public int Day { get; set; }
[DisplayFormat(DataFormatString = "{0:C}")]
public decimal Total { get; set; }
}
public class SalesVM
{
[DisplayFormat(DataFormatString = "{0:MMMM yyyy}")]
public DateTime Date { get; set; }
public List<DayTotalVM> Days { get; set; }
}
The sql query you have can be generated in linq and projected into your view models using
int year = 2014;
int month = 12;
var query = db.Sales.Where(x => x.Date.Year == year && x.Date.Month == month)
.GroupBy(x => x.Date).Select(g => new DayTotalVM
{
Day = g.Key.Day,
Total = g.Sum(x => x.Total)
})
However this will only give you the 2 items as per you above image, but from the comments you want to display all days in the month, so you can add
int daysInMonth = DateTime.DaysInMonth(year, month);
List<DayTotalVM> days = new List<DayTotalVM>();
for(int i = 1; i < daysInMonth + 1; i++)
{
DayTotalVM item = new DayTotalVM () { Day = i };
DayTotalVM ex = query.Where(x => x.Day == i).FirstOrDefault();
if (ex != null)
{
item.Total = ex.Total;
}
days.Add(item);
}
and finally initialize and return your view model
SalesVM model = new SalesVM();
{
Date = new DateTime(year, month, 1),
Days = days
}
return View(model);
And then the view would be
#model SalesVM
#Html.DisplayFor(m => m.Date);
<table>
#for(int i = 0; i < Model.Days.Count; i++)
{
<tr>
<td>#Html.DisplayFor(m => m.Days[i].Day)</td>
<td>#Html.DisplayFor(m => m.Days[i].Total)</td>
</tr>
}
</table>
Edit
The for loop could be replace by using a GroupJoin()
public ActionResult MonthlySalesByDate(int year, int month)
{
int daysInMonth = DateTime.DaysInMonth(year, month);
var days = Enumerable.Range(1, daysInMonth);
var query = db.Sales.Where(x => x.Date.Year == year && x.Date.Month == month).Select(g => new
{
Day = g.Date.Day,
Total = g.Total
});
var model = new SalesVM
{
Date = new DateTime(year, month, 1),
Days = days.GroupJoin(query, d => d, q => q.Day, (d, q) => new DayTotalVM
{
Day = d,
Total = q.Sum(x => x.Total)
}).ToList()
};
return View(model);
}

What is the equivalent DISTINCT(sql server) in the Linq

I have a Table(Send) with columns(Id, UserId,SendDate) and another table(Receive) with columns(Id,SendId,UserName).
I want show all records in SendTable with all RecieveUserName.
for example.
(Send)
1 1 2013
2 2 2013
(Recieve)
1 1 Jack
2 1 Ema
3 2 Alex
4 2 Sara
Result
1 1 2013 Jack, Ema
2 2 2013 Alex, Sara
I use this query in SqlServer (The DISTINCT keyword eliminates duplicate rows from the results of a SELECT statement)
SELECT DISTINCT c2.Id,
(SELECT STR( UserName )+ ','
FROM dbo.Reciver c1
WHERE c1.SendId = c2.id FOR XML PATH('')) Concatenated, c2.SendDate, c2.UserId
FROM dbo.Send AS c2 INNER JOIN
dbo.Reciver ON c2.Id = dbo.Reciver.SendId
How do this query in Linq?
Distinct is also available in LINQ.
For example
public class Product
{
public string Name { get; set; }
public int Code { get; set; }
}
Product[] products = { new Product { Name = "apple", Code = 9 },
new Product { Name = "orange", Code = 4 },
new Product { Name = "apple", Code = 10 },
new Product { Name = "lemon", Code = 9 } };
var lstDistProduct = products.Distinct();
foreach (Product p in list1)
{
Console.WriteLine(p.Code + " : " + p.Name);
}
Will return all rows.
var list1 = products.DistinctBy(x=> x.Code);
foreach (Product p in list1)
{
Console.WriteLine(p.Code + " : " + p.Name);
}
will return 9 and 4
It doesn't seem to me that you need to use Distinct in this Linq query. Assuming you have the relationships between tables set up on your linq datacontext, you can do something like this:
var result = from s in context.Send
select new {
id = s.Id,
userId = s.UserId,
date = s.SendDate,
users = s.Receive.Select(u => u.UserName)
}
Note: users will an IEnumerable<String> - you can use string.Join() on the client to join the names into a string.
Update
To return users as a string to first need to 'switch' to Linq To Objects by calling AsEnumerable() or ToList() and the Linq to Sql query.
var output = from s in result.AsEnumerable()
select new {
id = s.id,
userId = s.userId,
date = s.date,
users = string.Join(", ", s.users)
}
Also see Gert Arnolds answer for a good explanation.
What you want can only be done in two steps. Not because of the DISTINCT, but because of the FOR XML. The C# equivalent of the latter is String.Join(), but you can't use that in a linq to entities statement directly. So you must collect the required data first, then switch to linq to objects (by applying AsEnumerable) and then do the concatenation and distinct:
db.Sends
.Where(s => s.Receivers.Any())
.Select(s => new {
s.Id,
Concatenated = s.Receivers.Select(r => r.UserName)
s.SendDate,
s.UserId
})
.AsEnumerable()
.Select(x => new {
s.Id,
Concatenated = String.Join(", ", x.Concatenated)
s.SendDate,
s.UserId
})
.Distinct()

LinQ and WCF service Operation

I am having a problem getting some LinQ to work inside a WCF service operation:
[WebGet]
public IQueryable<StockItem> AllStockableItems(int LocationAddressId)
{
StockEntities svc = this.CurrentDataSource;
//get all the stock at a location
var StockAtLocation = from s in svc.Stock
where s.Location == Location
select s;
//weave it into the list of all stockable items
var StockableItems = from si in svc.StockableItems
join s in StockAtLocation on si.ItemId equals s.ItemId into tmp
select si <and somehow expand> si.Stock;
return StockableItems;
}
Problem is, I don't know how to expand the stock in the returned data?
A url like the following:
....my.svc/AllStockableItems?LocationAddressId=3&$expand=Stock
Will expand the stock for all locations, rather than just the location needed. Is this possible or is my best bet to make 2 seperate requests from the Silverlight client and do the joining client side?
Any help greatly appreciated.
Yes, example data, sorry for not putting it in first time around:
example stock data:
ItemId Location Quantity
1 1 4
1 2 3
1 3 2
2 2 6
3 3 0
7 1 3
7 2 0
example stockableItems data
ItemId <other columns>..
1
2
3
4
5
6
7
8
Say the locationAddressId paramter =2, I'm trying get the service operation to return (not literally, but in the Atom/Pub equivalent):
StockableItem { ItemId :1
Stock {
entry {
Stock {LocationId : 2, Qty :4}
}
}
}
StockableItem { ItemId :2 }
StockableItem { ItemId :3 }
StockableItem { ItemId :4 }
StockableItem { ItemId :5 }
StockableItem { ItemId :6 }
StockableItem { ItemId :7
Stock {
entry {
Stock {LocationId : 2, Qty :0}
}
}
}
StockableItem { ItemId :8 }
Thank you.
[Update 2]
Ok, I've tried a couple fo things; first off I gave this a go:
var StockableItems = from si in svc.AllStockableItems
join s in svc.Stock on si.ItemId equals s.ItemId
where s.Location == Location
select new StockableItem
{
ItemId = s.ItemId,
Stock = new EntityCollection<Stock>
{
new Stock()
{
Location = s.Location,
Quantity= s.Quantity
}
}
};
Which gave me:
The entity or complex type '...' cannot be constructed in a LINQ to Entities query
Which led me to here:
The entity cannot be constructed in a LINQ to Entities query
Which led me to re-write the query to this:
var StockableItems = svc.AllStockableItems
.Join(svc.Stock, si => si.ItemId, s => s.ItemId, (si, s) => si)
.ToList()
.Select(si => new StockableItem
{
ItemId = si.ItemId,
Stock = new EntityCollection<Stock>
{
new Stock()
{
Location = si.Stock.First().Location,
Quantity= si.Stock.First().Quantity
}
}
})
.AsQueryable();
Which returns all the StockableItems but, somewhat frustratingly, doesn't include any Stock. Have I simply made a boo boo in this last query? I suspect my inner projection of the Stock entity is incorrect?
Thanks Again
I think you're looking for something like this:
var StockableItems = from si in svc.StockableItems
join s in StockAtLocation on si.ItemId equals s.ItemId
select new
{
StockableItem = si,
Stock = s
};
You can choose how you project your output in the select clause. You can select the entire object, like above, or you can also select fields in your objects. For example:
select new
{
ItemId = si.ItemId,
Stock = s,
Qty = s.Quantity
};
Also, you may want to consider combining your two queries into a single query:
var StockableItems = from si in svc.StockableItems
join s in svc.Stock on si.ItemId equals s.ItemId
where s.Location == Location
select new
{
StockableItem = si,
Stock = s
};
And now one more example that shows you something really close to your example output:
var StockableItems = from si in svc.StockableItems
join s in svc.Stock on si.ItemId equals s.ItemId
where s.Location == Location
select new
{
StockableItem = new
{
ItemId = s.ItemId,
Stock = new
{
LocationId = s.Location,
Qty = s.Quantity
}
}
};
Update
I've made some adjustments to your modified query which uses the Join to create the data that is passed onto the rest of the query. I also put your Where clause back in there (if you want to use it there) to filter on Location. I also took the ToList() out of there because I'm not sure if it's necessary.
var StockableItems = svc.AllStockableItems
.Join(svc.Stock, si => si.ItemId, s => s.ItemId,
(si, s) => new
{
ItemId = si.ItemId,
Location = s.Location,
Quantity = s.Quantity
})
.Where(x => x.Location == Location)
//.ToList()
.Select(x => new StockableItem
{
ItemId = x.ItemId,
Stock = new EntityCollection<Stock>
{
new Stock()
{
Location = x.Location,
Quantity= x.Quantity
}
}
})
.AsQueryable();