I am using ASP.NET 3.5 with VB.net
I have a DataTable as such.
RpID LocationServed
---- --------------
1 St. Louis
1 Baltimore
1 Columbus
2 Chicago
2 St. Charles
2 Peoria
2 Nashville
3 Dallas
3 Miami
3 Indianapolis
What that for each Rep, I need to send an email with all of their Location Served.
I am not quite sure how do do this. I am using ASP.NET 4
My plan is to have 2 loops
<loop1 that has the group by of RepID>
<loop2 can go through the list of items for a given RepID >
strCity = do processing here that will compile a list of the cities for a given rep
</loop2 end>
<send out email a given RepID and then reset strCity >
<loop1 end>
But not quite sure what the best approach is to tackle this.
You can do this one of three ways.
Assuming the DataTable is sorted by RpID, have one loop, process each city. When RpID changes, send an email.
OR...
Loop on the data table. When RpID changes, call .Select on the data table and filter on RpID. Loop on the returned array of DataRows and process each city. Send an email.
OR...
Since you are using ASP.NET 4, you can use a LINQ query to get a distinct list of RpID from the datatable, loop on that list of RpIDs, and then in the loop, use a LINQ query on the datatable to get a list of cities from the datatable for that RpID. Send an email. See here (this talks about a DataSet, but it's the same thing, really)
Note that for any of these approaches, you will have to have a check after the loop to send an email for the last RpID processed.
You can do all this processing in two separate loops.
create a dictionary (possibly sorted) consisting of the Repids as keys and lists of cities as values in a single pass of the table.
process the dictionary. For each key, grab the associated list, (possibly sort it) and send the email.
It'd be a lot quicker than whatever you're proposing. IIRC #1 can be done purely in one LINQ statement as well, see: How to: Group Elements in a Sequence (LINQ to SQL)
Edit: This stackoverflow question seems related Efficient DataTable Group By
Related
I'm writing a music program with SQLite as a back-end and I'm trying to work out how to sort all the albums in the order I want them. In theory, this is pretty easy but there's just the odd one I'm having trouble with as below.
Take these three albums - how to I get them sorted in this order when using SELECT DISTINCT Album FROM Album ORDER BY Album COLLATE NOCASE:
Now That's What I Call Music! 10
Now That's What I Call Music! 99
Now That's What I Call Music! 100
As opposed to what they get sorted in which is:
Now That's What I Call Music! 10
Now That's What I Call Music! 100
Now That's What I Call Music! 99
I want 100 to follow 99, if that makes sense.
Shawn has given you an explanation of what you see, and a possibility of getting what you desire by writing a custom collation function.
But do you really have albums with names like "Now That's What I Call Music! 10"? My guess is the "10" is some sort of distinguishing code, in which case a better solution is to redesign your database schema to separate out the actual name from the distinguishing code, i.e., two separate columns. That way you can sort on both fields like ORDER BY Album_name, distinguishing code.
(When you create the table you will also probably want the combination of the two fields to be unique, like UNIQUE (Album_name, distinguishing_code))
I think the title makes this sound possibly more difficult then it is.
Basically, I have a Table called Orders. 18 Columns.
The PK is called ORDERID(Nvarchar).
The problem child is a field called CustomerID(nvarchar). Prior to my assignment, this field use to be populated with raw customer information(Customer1, Customer 2 etc.) However, sometime ago, it was decided to insert just the number corresponding to the customer from the customer table and perform the lookup at the front end. The records that have the raw customer data are existent in the customer table but the lookup won't work when it tries to parse the CustomerID to the customer table, when the text is present. It results in blank fields on the front end.
OrderID(PK) Inquiry# CustomerID
Z1 I1 Customer1 (Look up on front end does not work)
Z2 I2 23 (Look up on front end works)
A couple foreseeable solutions.
Repalce old customerID with the corresponding customer number
Modify query on frontend to only show records that were created after the change to customerID(text -> #) Then push a new front end to everyone(around 80 employees)
Extract the records that have a text value instead of a number and create a new table called something like dbo.OldOrders Again I'd have to push a new front end.
Ideally I'd like to the accomplish the first solution if at all possible.
Anyone have any advisement?
Could you create a view that converts it into a number and then pull from there?
The three tables of interest are:
Event, containing various details of, eg, the berlin marathon
Result, containing various fields including user's race time and a FK to an Event, and
Goal, with a FK to the Event the user would like to run, a field for the time they'd like to run it in, and eventually a FK to the Race at which the user achieved their goal.
Obviously, the Event of the Race where the user achieved their goal has to be the Event of the Goal. But not all Goal's have been achieved -- some may never be.
Is this bad design? Can anybody suggest a better way of modelling this problem? I'm using sqlite in a django project.
Your Event table is OK.
But your Goal Table design messed up the proposed event and the actual achieved event.
I think Result Table can be merged with Goal table into a new Result table.
Since one user may want to run multiple events. In your new Result table, it should be like:
UserID EventID TimeProposed ActualTimeUsed Achieved
1 1 1 hour 1.1 hour No
1 2 1.5 hour 1.2 hour Yes
So the loop you mentioned is removed since each row has only one event. (The UserID and EventID remains to be the FK to the other two tables.)
The Achived column can be updated using a query to decide ActualTimeUsed<=TimeProposed.
I know this has been asked before..sort of. And that's why I'm posting. Basically I'm building a report in Crystal that relies, to keep this simple, at least 3 tables.
Table A is inner joined to table B by a unique ID. Table B has a child table that may or may not have data related to this unqiue ID.
As a general example table A is a customer table, table B is a product table and the child table is contains the product number. All customers have a product, but not all customers have product number in the child table. I hope I've explained that simply enough.
My issue is sort of between Crytal and Access and how to query this. When I'm writing behind something in VB it's easy enough to write and execute a query and display the result in the desired manner. However I can't seem to get my query straight... I either end up with a report with cartesian product as the resultset, which displays ok...except that even with the few records I have ends up being about 30k pages..or I end up with a blank dataset because the child table does not have corrisponding data to B.
Using outter joins I've managed to get my results within some amount of reason but not acceptable to a real world report. I'm sure this issue has come up but I can't seem to find any suitable answers and to be honest I'm not even sure what questions to ask being a Crystal n00b.
What I'm really after is the data from Table A, the data from Table B and children tables. While they are logically linked and can be linked with the ID field, it isn't necessary I don't think because I am taking a parameter value for the report of the ID field. And once the tables are filtered, no other action needs to be taken except to dump them back on the report.
So can anybody point me in the right direction? Can I set up individual datasoruces (unrelated) based perhaps in a seperate section? Should I build a tree of queries and logic in my DB to get what I need out? I've been racking my brain and can't seem to find the right solution, any and all advice is apreciated and if I can clarify anything or answer any questions I will.
Thanks in advance.
As per requested below:
Section1
ID fname lname
01 john smith
Section2
ID notifiedDate notifiedTime
01 10/10/2012 12:35PM
S2childAdmin
ID noteName
01 jane doe
This data is logically related and can be related in the DB. However it is not necessary as long as the ID parameter is passed to each table. Querying Section1 inner joined with Section2 works fine. But any other arrangements result in more rows than required and I end up with a report many times duplicated. What I really need is something like Section1 joined with Section2 and S2childAdmin as a freely availble table. Otherwise it multiplies my data or results in a null recordset (because it can return 0 rows)
I think this should help point you in the right direction, though it has been 5 years or so since I did heavy Crystal Reports work.
One option might be to join everything using Outer Joins like you stated you were, then use a Crystal Report 'group' on the Table A ID, with a group based upon Table B ID inside of that. So you would, in the actual 'Detail' area put your table C details if there were any, and then use the Group header/footer for Table A and Table B to show data specific to those objects.
Another possible solution that may fall short of your requirements but might get you thinking in another way, is to create your main report and in it, display the fields from table A. Then below those fields include a sub-report and pass in the unique ID from Table A. You will then have a query inside of the subreport that finds all of the Table B records with that Table A.ID value and displays their details.
At this point you run into a weakness of Crystal Reports (at least as of the last version I used) in that you cannot have a subreport inside of a subreport.
I am new to Asp.Net, MVC3, Linq, and everything else related to it. I'm very used to PHP and ColdFusion so pardon my ignorance! Essentially what I am trying to do is re-create the situation in ColdFusion where I can perform the equivalent of a cfoutput's group attribute. I'm so used to just calling a stored procedure and then doing
<cfoutput group="id">
and then another inner cfoutput for any columns that have non-distinct data. Works like a charm! Not so much in Asp.Net.
I would like to stay with using my stored procedure, which is returning a join from two tables with a one-to-many relationship. For example's sake let's say I have 3 columns: a full name, a title, and a graduation year. The graduation year is the column from the joined table, so my result from the stored procedure looks like this:
Jim Professor 2005
Jim Professor 2008
Jim Professor 2011
I am sending this to the View. I am assuming it's the View's job to then group the data based on one of the columns (probably the full name). I want to output an HTML table with 3 columns and in this situation I would have ONE row:
Jim Professor 2005, 2008, 2011
I have googled tons of examples that use this thing called a group key. This does not seem to help me because I'm not interested in just outputting one value "Jim" (or whatever the grouped value is), I need both "Jim" and "Professor" values to be output for each row. My thinking is I would need 2 foreach loops, the outer loop displaying the fullname and title and the inner loop going through all possible matches for the graduation years. I cannot seem to get the graduation years in a group, especially with this IGrouping syntax. The key can only store one value and I need every value on that row, I only really need one or two values to be iterated over. Should I try and create a custom view model after I perform a secondary linq grouping and then send that to a strongly typed view?
EDIT:
Ok, I have code that works but it seems very inefficient as I basically have to re-define all of the columns/values that I have from my stored procedure. It almost makes me want to forget stored procedures and just use LINQ for everything. It seems what I was asking for is a kind of "group on multiple columns" and link helped immensely.
var records = db.getRecords();
var groups = from r in records
group r by new
{
r.id
}
into row
select new ListVM()
{
id = row.Key.id,
fullname = row.Select(x => x.fullname).First(),
title = row.Select(x => x.title).First(),
degrees = row.Select(x => x.degree_name).ToList(),
majors = row.Select(x => x.major_name).ToList()
};
return View(groups);
I of course had to create a ViewModel for this to work. In my view then I can use for loops to iterate over the degrees and majors lists. Is this the best way to do this? I just generally need more than just the group key to display my entire row of information, and only want to iterate over lists once or twice in a 20 column row, as opposed to only displaying the group key once and iterating over everything in most examples I see.
I'm not that big specialist with Linq and MVC, but faced with your problem I would:
Deal with data preparation in controller/model, after being taught that view should be concerned with displaying things only.
I would use knowledge from these topics to solve your particular problem:
a) grouping by multiple columns:
Group By Multiple Columns
b) Concatenation as an aggregate function:
Using LINQ to concatenate strings
c) Using aggregates and grouping by multiple columns
How to write a LINQ query combining group by and aggregates?
Once you have data in your view model, just display it.
I believe I've finally found out how to solve what I was looking for. A "group join" seems to solve my problem with ease. The information I found on this page solved it: http://geekswithblogs.net/WillSmith/archive/2008/05/28/linq-joins-and-groupings.aspx