tags:

views:

190

answers:

2

I am trying to get top countries list froma list of ips in my database, With sql query i return a data table consist of data like below

IP IpCount

+++++++++++++++++++

XXX.XXX.XX1 20

XXX.XXX.XX2 1

XXX.XXX.XX3 2

On data bind to a repeater control im using Maxmind Ip to Country db to get country name

Utils.GetCountryNameAndFlag(Eval("ip").ToString())

As you would imagine if some IPs are from same country i get same country listed couple of times in repeater control like

USA - 3

USA - 1

DE - 2

What i am trying to achive is to do a query to my data table to group by country name and add number of IPs from that country so result woul be

USA - 4

De - 2

I can not do this on sql server side because my function gets country name from a binary file in file system (see http://www.maxmind.com/app/csharp)

update:


with Lee's help i got below query working but in that query instead of CountryName=group.Key i want to select row "CountryName"

TopCountriesRepeater.DataSource = ds.Tables[1].AsEnumerable()
            .GroupBy(row => row.Field<string>("CountryCode"))
            .Select(group => new
            {
                CountryCode = group.Key,
                CountryName = group.Key,
                UsersFromIp = group.Sum(row => row.Field<int>("UsersFromIp"))

            }
            );

Update 2

I've got it working with

            var query = from row in ds.Tables[1].AsEnumerable()
                    group row by new
                    {
                        CountryCode = row.Field<string>("CountryCode"),
                        CountryName = row.Field<string>("CountryName")
                    } 
                    into grp orderby grp.Sum(r => r.Field<int>("UsersFromIp")) descending
                    select new
                    {
                        CountryCode = grp.Key.CountryCode,
                        CountryName = grp.Key.CountryName,
                        UsersFromIp = grp.Sum(r => r.Field<int>("UsersFromIp"))
                    };
A: 

This sample seems like it may help you work it out. http://www.develop-one.net/blog/2007/11/11/LINQSumAndGroupBy.aspx

Jason Kostempski
+2  A: 

Given a datatable dt, I think this should work:

dt.AsEnumerable()
            .GroupBy(row => Utils.GetCountryNameAndFlag(row.Field<string>("ip")))
            .Select(group => new { Country = group.Key, Count = group.Count() });

EDIT: In response to your comments - since the IGrouping is an IEnumerable<DataRow> you can simply get the country name from any of the values in it. Therefore you be able to do this to get what you want:

TopCountriesRepeater.DataSource = ds.Tables[1]
.AsEnumerable()
.GroupBy(row => row.Field<string>("CountryCode"))
.Select(group => new { CountryCode = group.Key, CountryName = group.First().Field<string>("CountryName"), UsersFromIp = group.Sum(row => row.Field<int>("UsersFromId")) } );
Lee
thanks. with your help i managed to do this----- TopCountriesRepeater.DataSource = ds.Tables[1].AsEnumerable() .GroupBy(row => row.Field<string>("CountryCode")) .Select(group => new { CountryCode = group.Key, CountryName = group.Key, UsersFromIp = group.Sum(row => row.Field<int>("UsersFromIp")) } );-----but i want to select CountryName from row too. how can i do that? I'm sure it is quite simple but can;t figure it out
nLL
instead of CountryName = group.Key i want to select row "CountryName"
nLL
i get system.data.row does not contain defination for getField error but with your help i was able get what i want. see my last edit
nLL
Sorry yes, it should be Field not GetField
Lee