Creating a monthly report and compare rows based on the sum - c#

This is my first time using c# and sql server to code a simple monthly reporting application which will print the report to paper.
Everything just fine but there is a complicated problem for me when comparing two value.
Suppose there are 14 columns(originally 37 columns) and 12 rows for each month. The last column i am using for month name.
Columns are:
Name, col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,monthName.
Logically there will be 12 reports in a year.
col2+col5+col6
and
col7+col10+col11 sum of current month's
must be same as last month col4 and col9-12 rows
This is my main problem!
For example if monthName has January(as past month) and I am filling the current month February . There is a pushButton called "Verify".
If I click on verify then the February's 3 columns sum will be compared to January's 1 column sum as above.
I have tried some sql query like select * from table1 where sum(col4)=sum(col2+col5+col6) and sum(col9)=sum(col7+col10+col11)
But my logic and knowledge is completely flawed since it did not work as expected.
Secondly, I thought appending data from sql query results to List<> and comparing the col4/col9 would be an idea but again flawed as there is no gurantee that Name column's value would not be shuffled which will lead to compare to wrong data, also I am not confident at it.
I need help from c# and sql database expert to get an idea to do this as I am not sure what is my options!
Update: I am doing some experiment in visual studio. All codes are just ugly but i will upload it on dropbox if someone care to try it.

I think your best solution here is to keep the business logic and the database query separate. If the user clicks the "verify" button on the "February" row, you just submit a database query along the lines of SELECT * FROM table1 WHERE monthName = 'january' although:
Probably you should actually use a date field to identify your months).
How you actually retrieve the data will depend on what type of data access you are using (ADO.NET, Entity Framework, etc.)
Once you get back that result, you just use straightforward C# logic to do the verification, along the lines of:
int priorMonthSum1 = priorMonthResultset.col4;
int priorMonthSum2 = priorMonthResultset.col9 + priorMonthResultset.col10 + priorMonthResultset.col11 + priorMonthResultset.col12;
int currentMonthSum1 = currentMonthResultset.col2 + currentMonthResultset.col5 + currentMonthResultset.col6;
int currentMonthSum2 = currentMonthResultset.col7 + currentMonthResultset.col10 + currentMonthResultset.col1;
if(priorMonthSum1 != currentMonthSum1 || priorMonthSum2 != currentMonthSum2)
{
// handle mismatch (highlight red?)
}
else
{
// handle match (highlight green?)
}

Related

Update query with one unique value other one with varying values

Want a query possibly a single query for the below conditions
To be updated value of column 3 and 4 is same for all 4 R2IGTNo column
Sometimes the blend will be up to 3 only, 4th row may not come
In C# application user will update for the first row (blend 1), other values have to be updated automatically since the values are the same.
I need a query, expert please help with this... Thanks
User picks row 1, this means your C# can know "Lot21009BB1C3" (putting text instead of image would have let me copy it, btw) but you write like the c# app doesn't know any other row..
Which means you can run a query:
UPDATE t SET HtrOnBy = #HtrOnBy, ChtrOnRemark = #ChtrOnRemark
WHERE R2IGTNo LIKE #R2IGTNo
And your c# shall put the following values:
#HtrOnBy = "Whatever it knows the first row HtrOnBy is"
#ChtrOnRemark = "Whatever it knows the first row ChtrOnRemark is"
#R2IGTNo = firstRowR2IGTNo.Remove(9) + "%"
We take the first 9 characters of R2IGTNo and add a percent. SQL will update all the rows that start with those, doesn't matter if it's 3 or 4 etc
If the number of chars varies, then you will have to get more smart about how you do your substring, such as looking for the first character after the numbers (eg regex)

Simple SUM Query needed for C#

I am a beginner programmer wanna ask about simple SUM query for C#. here is the case:
I have a table called "revenue", and that table consist of 5 columns. they are Bulan, Target, Realisasi, Target_YtD, and Realisasi_YtD. for column Bulan, I manually inserted 12 data. they are January, Februari, March, and so on...
For column Target and Realisasi also I inserted data manually with INT data type.
Now, I wanna add up the January's Target + February's Target + March's Target, and then the value of that calculation is gonna fill March's Target_YtD.
Can somebody tell me the query of that? I hope anyone can help me this time, I really appreciate that. Thanks
Do you mean something like this?
UPDATE
SET Target_YtD =
(SELECT SUM(Target) AS Total FROM revenue
WHERE Bulan IN ('JAnuary', 'February', 'March')
)
WHERE Bulan = 'March'
It depends on if you plan to calculate the colum at the time of input and save it to the database. Usually calculated columns are not in and of themselves columns in databases, but if that is what you are doing you can just use the c# concatenation function to populate that variable before doing your insert statement. If you're only populating the sum upon output to a c# app, same thing applies, or you could do a sum in your sql code. A few ways to get there, just depends what you're trying to do.

Why does access return inconsistent results when searching between dates?

So I have a little piece of software my work is running to help with receiving and inventory ATM. I made a report to pull item entries between Date A and B. I use the MonthCalendar Control and then pull the date range using the .SelectionStart and .SelectionEnd properties of the control, as the user will typically select a week ( mon-fri ) for reporting.
Heres the SQL I send to my Access DB:
InvDB.GetQuery("
SELECT
[_Date],Commodity,Gross,Net,Description
FROM
Tags
WHERE
Format([_Date],'yyyy') = '" + DateTime.Now.Year.ToString() + "' AND
Format([_Date],'m/d/yyyy') Between #" + monthCalendar1.SelectionStart.ToString("M/dd/yyyy") + "# AND #" + monthCalendar1.SelectionEnd.ToString("M/dd/yyyy") + "#
AND NOT Category = 'Finished Goods'
ORDER BY [_Date] Asc",
"Tags");
Dates are stored in this format: "9/1/2015 10:31:50 AM"
I was never able to get the in SQL date functions working initially so I had to resort to this method, which I am sadly aware is greatly inefficient...
First the reason why I went with the Year comparison, is because when I was selection a date range, access was returning all years associated with the dates. Not only the one that the properties returned. ( I also know this will cause issues if dealing between years of course )
And finally the reason why I ask the question here, is that when the user selects the dates, and tries to get the items between the dates... The returned selection, is so random... I've never seen the type of obscure results this SQL returns... I can't even see a pattern to it. I select one week, and it only gives 3 of the 5 days out of that week along with the first two weeks of the previous month... Another week selection is accurate... Another yet, gives 2 of the 5 days of that week...
Edit - Based on the suggestion below, I now push query through with parameters. I also removed the SQL Format() after testing still yielded the same randomness. This simple query so far, is returning accurate information.
SELECT
[_Date],Commodity,Gross,Net,Description
FROM
Tags
WHERE
[_Date] Between ? AND ?
AND NOT Category = 'Finished Goods'
ORDER BY
[_Date] Asc
Try not to convert the [_Date] to string. You wouldn't be able to use the BETWEEN correctly for date when you convert it.

How To Quickly Update All The Rows In A Table With New Value From A C# Program

I have been given a table that has over 2 Billion rows in it. It has a field for time entered but the creator of the table made this field a string field. It also does not follow normal date-time conventions.
I have been tasked to create a new field that is a datetime type field containing the same time but converted to be proper format so that queries can be run on it.
Currently I have written a C# console application that SELECTS the top 100000 rows that have not been updated yet and row by row converts the string to a time. It then updates each of the rows.
This process works but it is slow and time is of the essence. I can run multiple copies of my program and am trying to come up with a solution to somehow run the program multiple times and make sure each copy of the program is updating different rows.
Ideas so far:
instead of selecting top 100000 rows, select 1000000 random rows. (there may be some overlap but it would get the job done)
this table has an id field. I could do a select where id modulo 2 == 0 for one program, id % 2 != 0 for another (this could continue for prime numbers etc.)
get rows only within an id range that is specified for each copy of the program I have running
add a locked column to tell my program that a field is currently locked (which would represent that it is being processed)
Can anyone provide a better suggestion? Improve on one of mine?
Thanks.
UPDATE: an example of my existing time string is 12/Nov/2014:08:52:22 and it needs to be converted to 2014-11-12 08:42:22
Use LINQ to SQL and only pull a certain amount of records at a time.
Your code would look something along these lines:
using (var db = new MyDbContext())
{
var results = db.GetResultsFromDatabase();
int take = 100;
int processed = 0;
while(processed < results.Count())
{
var set = results.Skip(processed).Take(take);
set.ForEach(s => {
// update the date
}
processed += take;
}
db.SubmitChanges();
}
So here is my solution, I have no idea how efective is for 2mil rows, in case you want to do it in SQL.
Declare #string varchar(50) = '12/Nov/2014:08:52:22'
SELECT CONVERT(datetime,REPLACE(SUBSTRING(#string,0,CHARINDEX ( ':' ,#string , 0)),'/',' ')
+' '+
SUBSTRING(#string,CHARINDEX ( ':' ,#string , 0)+1,LEN(#string)),120)
Let me explain you a bit the code
REPLACE(SUBSTRING(#string,0,CHARINDEX ( ':' ,#string , 0)),'/',' ')
replaces the "/" chars from the date and returns 12 Nov 2014
SUBSTRING(#string,CHARINDEX ( ':' ,#string , 0)+1,LEN(#string)),120)
get the time without the ":" between the date and time from your initial string.
Finally added a space between this two string manipulations and converted it to datetime.
Output for the query above : '2014-11-12 08:52:22.000'
Just do it inside SQL instead of reading the entire database and working it.
use the following :
UPDATE <TableName>
SET <dateTime-Date> = CONVERT(datetime, <string-Date>)
check this site for any format specifications you would like :
SQL Datetime Conversion

Taking duplicate lines and squeezing them into 1 row on SQL Server 2008 R2?

I'm trying to write a stored procedure in SQL Server that will eliminate some logic in my C# program. What I'm doing right now is the query is in a view. Then I'm making a list with the view.
List<MyView> listOrdered = new List<MyView>();
Here's where it gets hairy. The query returns rows that are duplicates. I don't want to delete the duplicate rows I want to combine them into 1 row. The rows are identical except for 1 column.
Example:
UID Name Age Child
1 John 50 Sally
1 John 50 Steve
2 Joseph 42 Timmy
2 Joseph 42 Billy
So what I'm doing in C# is writing logic that says: (pseudo code)
foreach(item in list)
{
if (UID != UIDCurrent)
{
Build Row
AppendRow to list
}
else
{
Append Child Column to Current Child Column
}
}
Basically it gives me:
UID Name Age Children
1 John 50 Sally, Steve
But instead of doing this logic in C# I would like to do this a stored procedure. So how I can I get SQL Server to combine the children column for each row instead of multiple rows.
If you need anything else to help you help me I will respond.
Oh guys believe me I don't want to do it this way either. The Database I'm using is huge and complex and doing this with C# was sensible and works but I've been asked to turn my function that does this in C# into a stored procedure. I just want to see if this is even possible.
This demonstrates a poor table design. Fix it at the root and then you don't have this silly logic in either your db or C# code.
instead of
people(UID, Name, Age, Child)
try
people(UID, Name, DateOfBirth)
children(Parent references people.UID, child references people.UID)
You can leave age instead of moving to date of birth but it's really a much better idea to do it this way.
This should work if you want to do this in the database, though you should think about doing it in the front-end.
SELECT UID,
Name,
Age,
STUFF(
(SELECT ',' + Child AS [text()]
FROM parentChildren b
WHERE a.UID = b.UID
FOR XML PATH('')),1,1,'') [ChildConcat]
FROM parentChildren a
This is 100%, without a doubt something to be handled in your application code, NOT in the database!
SQL performs fairly poorly in string manipulation operations, especially compared to iterative languages like C#. You want your database to pass you the actual DATA, and then how you display that to be handled in the application layer.
Any attempt to solve this in SQL will be slower and harder to maintain than a version in your application code.

Categories

Resources