I'm working on a maps application and need to be able to pare down a giant dataset of location values into more reasonable values. So what I'd like to do is group the positions by rounded values like the following SQL:
select ROUND(Latitude, 0), ROUND(Longitude, 0), count(*) from tweet
group by ROUND(Latitude, 0), ROUND(Longitude, 0)
order by count(*) desc
I can never get grouping to work the way I need it to though with EF and/or LINQ (mainly because I can't seem to understand how it works). Ideally I would prefer to have it right in the EF query so that it becomes part of the SQL statement and I don't have to bring the giant dataset into a List before performing some LINQ operation on it...but if it has to be done that way then so be it.
I can do it this way, but I don't want to:
var items = context.ExecuteStoreQuery<DataPoint>("select ROUND(Latitude, 0) as lat, ROUND(Longitude, 0)as lon, count(*) as weight from location " +
"group by ROUND(Latitude, 0), ROUND(Longitude, 0) " +
"order by count(*) desc", null).ToList();
Edit:
Final solution (with a bit of back and forth) accepted below ended up looking like this:
private class DataPoint
{
public double lat { get; set; }
public double lon { get; set; }
public int weight { get; set; }
}
var mydata = (from t in locations
group t by new {
Latitude = EntityFunctions.Truncate(t.Latitude, accuracy).Value,
Longitude = EntityFunctions.Truncate(t.Longitude, accuracy).Value }
into g
orderby g.Count()
select new DataPoint{ lat = g.Key.Latitude, lon = g.Key.Longitude, weight = g.Count() }).ToList();
Don't forget to add this using statement:
using System.Data.Objects;
from t in context.Tweets
group t by new { t.Latitude, t.Longitude } into g
order by g.Count() desc
select new { g.Key.Latitude, g.Key.Longitude, Count = g.Count() }
Related
These are my two tables:
publicParking(publicParkingID, address, latitude, longtitude, status,
PricePerHour, maxSpaces, occupiedSpaces, freeSpaces, isOrdered)
and
parkingLot(parkingLotID, address, latitude, longtitude, status,
PricePerHour, maxSpaces, occupiedSpaces, freeSpaces, isOrdered)
All of the columns are the same except the ID.
I need to write query in LINQ that will return a table ordered by price with all the available parkings (publicParking / parkingLot) - with status==true.
The table should look like this:
ID address latitude longitude status
Should I do a union, or should I change the table so the first column will call just ID? (instead of publicParkingID and parkingLotID)
I've tried this code but it does not work
var union =
(from lot in parkingLots
where lot.status == true
select lot).Union( from pub in publicParkings
where pub.status==true
select pub);
It give this error :
I am working with LINQPad5 and with code editor of tutorialsteacher. Are there are other options?
To use Union both result sequences must contain the same types. In your example the outer query contains parkingLot and the inner publicParking.
It could be solved using anonymous types:
var union =
(from lot in parkingLots
where lot.status == true
orderby lot.PricePerHour // don't forget ordering
select new {
ID = lot.parkingLotID,
lot.address, lot.latitude, lot.longitude, lot.status})
.Union(from pub in publicParkings
where pub.status==true
orderby pub.PricePerHour // don't forget ordering
select new {
ID = pub.publicParkingID,
pub.address, pub.latitude, pub.longitude, pub.status});
But maybe better for further data handling would be a custom class:
public class ParkingData
{
public int ID {get; set;}
public string Address {get; set;}
public double Latitude {get; set;}
public string Longitude {get; set;}
public bool Status {get; set;}
}
and query like that:
var union =
(from lot in parkingLots
where lot.status == true
orderby lot.PricePerHour // don't forget ordering
select new ParkingData {
ID = lot.parkingLotID,
Address = lot.address,
Latitude = lot.latitude,
Longitude = lot.longitude,
Status = lot.status})
.Union(from pub in publicParkings
where pub.status==true
orderby pub.PricePerHour // don't forget ordering
select new {
select new ParkingData {
ID = pub.publicParkingID,
Address = pub.address,
Latitude = pub.latitude,
Longitude = pub.longitude,
Status = pub.status});
I have a list of objects in table tblB which is retrieved from db in following format.
public class playdata
{
public string consumerid { get; set; }
public string play_time { get; set; }
public string genre{ get; set; }
.
.
.
public int mycounter{ get; set; }
}
I have a table tblA which has a column colA which has int from 0 to 1000.
I wish to create a linq query similar to sql as below..
Select x.i as numindex, y.consumerid,y.play_time,y.genre
From
(Select colA as i from tblA) x
left join
(
Select consumerid, play_time,genre,mycounter from tblB
)y on y.mycounter > x.i
I tried the following unsuccessfully..
I came to find that Enumerable.Range(0, 1001) generated a numeric series so no need to get that table data..
List<playdata> plays = .....
var q= (from s in Enumerable.Range(0, 1001)
join p in plays on s < p.mycounter into t
from rt in t.DefaultIfEmpty() select new{
numindex=s,
consumerid=p.consumerid,
play_time =p.play_time,
genre=p.genre
}).ToList();
I see two errors in second line..
p is not in scope of left side of equals .. I have also tried..p.mycounter>s with same result.
The other error is in into where it shows.. expected contextual keyword equals
The errors go away if I change the second line to..
join p in plays on s equals p.mycounter into t
All help is sincerely appreciated.
Thanks
You have to use the alternative way of representing left outer join in LINQ:
var q =
(from i in Enumerable.Range(0, 1001)
from p in plays.Where(x => x.mycounter > i).DefaultIfEmpty()
select new
{
numindex = i,
consumerid = p?.consumerid,
play_time = p?.play_time,
genre = p?.genre
}).ToList();
Note that in LINQ to Objects you have to account for right side of the left outer join returning null when there is no matching element, otherwise you'll get NullReferenceException.
I am looking for a LINQ to use with my datatable and display all the duplicate rows based on certain columns in windows form datagrid view.
The LINQ should give a result similar to the plain old below give SQL.
SELECT *
FROM Table1 t
JOIN ( SELECT Taskid, Studentid, DateChangeid
FROM Table1
GROUP BY Taskid, studentid, datechangeid
HAVING COUNT(*) > 1) temp
ON t.taskid = temp.taskid AND t.studentid= temp.studentid AND t.datechangeid= temp.datechangeid
This should do what you want:
var result =
t.GroupBy(g => new {TaskId = Taskid, StudentId = studentid, DatechangeId = datechangeid})
.Where(g => g.Count > 1)
.ToList();
Now you're joining Table1 on Table1 which isn't needed, just do the filtering on Table1 only.
Now the result will be of type List<IGrouping<'a,Table1>> though because of the anonymous keyselector, you can also define TaskId , StudentId and DateChangeID in a class to get rid of that. For example:
public class Table1GroupKey
{
public int TaskId {get; set;}
public int StudentId {get; set;}
public int DateChangeId {get; set;}
}
Then you can use:
GroupBy(g => new Table1GroupKey { ... })
And your result will be List<IGrouping<Table1GroupKey,Table1>>.
I managed it by writing two linq as given below.
var RepeatedValues = from d in DataTableitems.AsEnumerable()
group d by d.Field<string>("MobileNo") into itemGroup
where itemGroup.Count() > 1
select new { name = itemGroup.Key };
var RepeatedInRows= from d in DataTableitems.AsEnumerable()
join c in RepeatedValues.AsEnumerable() on d.Field<string>
("MobileNo") equals c.name
select d;
I have the following query:
var rowData = companies.Select(
t => new CompanyDetail
{
CompanyID = t.Title,
Subjects = subjects.Count ( u => t.RowKey == "0000" + u.PartitionKey)
}).ToList();
public class CompanyDetail
{
[DisplayName("Company")]
public string CompanyID { get; set; }
[DisplayName("Subjects")]
public Int32 Subjects { get; set; }
}
The query output looks like this:
CompanyID Subjects
1 2
2 4
3 1
However I have a problem if the company has no subjects. I would like to see:
CompanyID Subjects
1 2
2 4
3 1
4 0
Is there a way that I can convert this LINQ query into an outer join so it always reports every company and then gives a count of how many subjects are connected through the row and partitionkey connector?
It's hard to answer this without knowing what LINQ provider you are using - your query would work as you expect in LINQ to Objects, for example.
Perhaps it would be worth a try to use an explicit GroupJoin to convince the provider to give you empty groups:
var rowData = from company in companies
join subject in subjects
on company.RowKey equals "0000" + subject.PartitionKey
into companySubjectGroup
select new
{
CompanyID = company.Title,
Subjects = companySubjectGroup.Count()
};
I have the following working TSQL query in ms SQL 2008
SELECT
Date,
COUNT(click) AS clicks,
COUNT(sale) AS sales,
count(lead) as leads
FROM
(
SELECT ClickDate as date ,ID AS click ,CAST(NULL AS int) AS sale , CAST(null as int) as lead
FROM clicks
UNION ALL
SELECT Date,null, ID ,NULL
FROM sales
UNION ALL
SELECT Date,null, NULL ,ID
FROM leads
) t
GROUP BY Date
How would i convert this to LINQ to SQL?
I wrote this LINQ but it doesn't work.
public class mydata
{
public DateTime date { get; set; }
public int? click { get; set; }
public int? sale { get; set; }
public int? lead { get; set; }
}
var clicks = from c in Clicks
select new mydata
{
date = c.ClickDate, click = c.ID, sale = null, lead = null
};
var sales = from s in Sales
select new mydata
{
date = s.Date, click = null, sale = s.ID, lead = null
};
var leads = from l in Leads
select new mydata
{
date = l.Date, click = null, sale = null, lead = l.ID
};
var v = clicks.Concat(sales).Concat(leads);
var res = from x in v
group x by x.date into xg
select new
{
date = xg.Key, clicks = xg.Count(z => z.click != null)
};
}
How do i correct this LINQ query?
Update:
i Modified the LINQ query based on David B recommendation.
i'm still getting the following error:
"All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists."
David's correct about the first two issues. For your final problem (3), Count() does not work like it does in SQL. It expects a predicate that returns a bool. Your using it with ints (i.e. z.click, z.sales, etc.)
The problem is that the anonymous types in the projections are not identical... ID is int in one and Nullable<int> in another.
Instead of using an anonymous type in your projections, use this:
public class ConcatTarget
{
public DateTime TheDate {get;set;}
public int? ID {get;set;}
public string sale {get;set;}
public string lead {get;set;}
}
Even though no instances are actually constructed, LinqToSql uses the class's shape to translate the query.
As for Count, perhaps you meant .Count(x => x.Prop != null) ?
Ok, apparently you've hit upon a buggy translation behavior as described here.
What's happening is the sql translator sees the null assignments, and throws them away. This causes an incorrect number of sql columns to be selected between the sets.
Here's a possible workaround:
int? myNull = null;
var clicks =
from c in Clicks
select new mydata
{
date = c.ClickDate,
click = c.ID,
sale = c.ID + myNull,
lead = myNull + c.ID //note - expressions must be unique
};
The basic idea is to create unique expressions the query translator can't throw away. This is harder than it sounds (above is my ninth attempt).
Here's the other two tables:
var sales = from s in Sales
select new mydata
{
date = s.Date,
click = s.ID + myNull,
sale = s.ID,
lead = myNull + s.ID
};
var leads = from l in Leads
select new mydata
{
date = l.Date,
click = l.ID + myNull,
sale = myNull + l.ID,
lead = l.ID
};
If you had more than 2 columns-to-be-nulled, you could resort to subtraction, division, multiplication, etc.