Sum of a particular column using LINQ - c#

Using the below mentioned query I am getting the all the values of a column called
promotionValue . I want to get the sum of all the values of *matched *
var matched = from table1 in dvtempPropertyRoomRatePromotion.ToTable().AsEnumerable()
join table2 in dvPropertyRooms.ToTable().AsEnumerable() on
table1.Field<DateTime>("RateDate") equals table2.Field<DateTime>("RateDate")
where table1.Field<DateTime>("RateDate") == table2.Field<DateTime>("RateDate")
select table1.Field<string>("promotionValue");

You need to parse the string to int or decimal:
var matched = from r1 in dvtempPropertyRoomRatePromotion.ToTable().AsEnumerable()
join r2 in dvPropertyRooms.ToTable().AsEnumerable()
on r1.Field<DateTime>("RateDate").Date equals r2.Field<DateTime>("RateDate").Date
select decimal.Parse(r1.Field<string>("promotionValue"));
decimal sum = matched.Sum();
Note that i've also changed some other things like the redundant where (since you've already joined these tables) or the Date property of DateTime.
Apart from that
why do you need the DataView at all? ToTable creates always a new DataTable. Why don't you use Linq-To-DataSet for all? I assume you've used the DataView for filtering, use Enumerable.Where instead. That would be more consistent, more efficient and more readable.
why is the column promotionValue a string? You should store it as a numeric type.

Here I m putting on simple query for sum of the two column of the different table.
SELECT
res.Date
,res.Cost
, res.Cost+res_con.Cost
FROM [ExpenseMst] res
inner join [ExpenseMst_2] res_con on res_con.ID =res.ID
Date | cost 1 | cost 2| total
2014-03-04 | 5200 |5200 |10400
2014-03-04 | 5012 |5012 |10024
2014-03-22 |100 |100 |200
2014-03-13 |25 |25 |50
2014-02-22 | 120 |120 |240
I hope it is useful..
:)

you can do
int sum = 0;
foreach(int match in matched)
{
sum = sum + match;
}

Related

LINQ join to return dynamic column list

I'm looking for a way to return a dynamic column list from a LINQ join of two datatables.
First, this is not a duplicate. I have already studied and discarded:
C# LINQ list select columns dynamically from a joined dataset
Creating a LINQ select from multiple tables
How to do a LINQ join that behaves exactly like a physical database inner join?
(and many others)
Here is my starting point:
public static DataTable JoinDataTables(DataTable dt1, DataTable dt2, string table1KeyField, string table2KeyField, string[] columns) {
DataTable result = ( from dataRows1 in dt1.AsEnumerable()
join dataRows2 in dt2.AsEnumerable()
on dataRows1.Field<string>(table1KeyField) equals dataRows2.Field<string>(table2KeyField)
[...I NEED HELP HERE with the SELECT....]).CopyToDataTable();
return result;
}
A few notes and requirements:
There is no database engine. The data sources are large CSV files (500K+ records) being read into c# DataTables.
Because the CSVs are large, looping through each record in the join is a bad solution for performance reasons. I've already tried record looping and it's just too slow. I get great performance on the join above, but I can't find a way to have it return just the columns I want (specified by the caller) without looping records.
If I need to loop over columns in the join, that is perfectly fine, I just don't want to loop rows.
I want to be able to pass in an array of column names and return just those columns in the resulting DataTable. If both datatables being passed in happen to have a column named the same, and if that column is in my array of column names, just pass back either column because the data will be the same between the 2 columns in that case.
If I need to pass in 2 arrays (1 for each datatable's desired columns) that's fine, but 1 array of column names would be ideal.
The column list cannot be static and hardcoded into the function. The reason is because my JoinDataTables() is called from many different places in my system in order to join a wide variety of CSVs-turned-datatables, and each CSV file has very different columns.
I don't want all columns returned in the resulting DataTable -- just the columns I specify in the columns array.
So suppose, before calling JoinDataTables(), I have the following 2 datatables:
Table: T1
T1A T1B T1C T1D
==================
10 AA H1 Foo1
11 AB H1 Foo2
12 AA H2 Foo1
13 AB H2 Foo2
Table: T2
T2A T2X T2Y T2Z
==================
12 N1 O1 Yeah1
17 N2 O2 Yeah2
18 N3 O1 Yeah1
19 N4 O2 Yeah2
Now suppose we join these 2 tables like so:
ON T1.T1A = T2.T2A
select * from [join]
and that yields this resultset:
T1A T1B T1C T1D T2A T2X T2Y T2Z
====================================
12 AA H2 Foo1 12 N1 O1 Yeah1
Notice that only 1 row is yielded by the join.
Now to the crux of my question. Suppose that for a given use case, I want to return only 4 columns from this join: T1A, T1D, T2A, and T2Y. So my resultset would then look like this:
T1A T1D T2A T2Y
==================
12 Foo1 12 O1
I'd like to be able to call my JoinDataTables function like so:
DataTable dt = JoinDataTables(dt1, dt2, "T1A", "T2A", new string[] {"T1A", "T1D", "T2A", "T2Y"});
Keeping in mind performance and the fact that I don't want to loop through records (because it's slow for large sets of data), how can this be accomplished? (The join is already working well, now I just need a correct select segment (whether via new{..} or whatever you think)).
I cannot accept a solution with a hardcoded column list inside the function. I have found examples of that approach all over SO.
Any ideas?
EDIT: I'd be ok getting ALL columns back every time, but every attempt I've made to include all columns has resulted in some kind of FULL OUTER JOIN or CROSS JOIN, returning orders of magnitude more records than it should. So, I'd be open to getting all columns back, as long as I don't get the cross join.
I'm not sure of the performance with 500k records, but here is an attempted solution.
Since you are combining two subsets of DataRows from different tables, there are no easy operations that will create the subset or create a new DataTable from the subsets (though I have an extension method for flattening an IEnumerable<anon> where anon = new { DataRow1, DataRow2, ... } from a join, it would probably be slow for you).
Instead, I pre-create an answer DataTable with the columns requested and then use LINQ to build the value arrays to be added as the rows.
public static DataTable JoinDataTables(DataTable dt1, DataTable dt2, string table1KeyField, string table2KeyField, string[] columns) {
var rtnCols1 = dt1.Columns.Cast<DataColumn>().Where(dc => columns.Contains(dc.ColumnName)).ToList();
var rc1 = rtnCols1.Select(dc => dc.ColumnName).ToList();
var rtnCols2 = dt2.Columns.Cast<DataColumn>().Where(dc => columns.Contains(dc.ColumnName) && !rc1.Contains(dc.ColumnName)).ToList();
var rc2 = rtnCols2.Select(dc => dc.ColumnName).ToList();
var work = from dataRows1 in dt1.AsEnumerable()
join dataRows2 in dt2.AsEnumerable()
on dataRows1.Field<string>(table1KeyField) equals dataRows2.Field<string>(table2KeyField)
select (from c1 in rc1 select dataRows1[c1]).Concat(from c2 in rc2 select dataRows2[c2]).ToArray();
var result = new DataTable();
foreach (var rc in rtnCols1)
result.Columns.Add(rc.ColumnName, rc.DataType);
foreach (var rc in rtnCols2)
result.Columns.Add(rc.ColumnName, rc.DataType);
foreach (var rowVals in work)
result.Rows.Add(rowVals);
return result;
}
Since you were using query syntax, I did as well, but normally I would probably do the select like so:
select rc1.Select(c1 => dataRows1[c1]).Concat(rc2.Select(c2 => dataRows2[c2])).ToArray();
Updated: It is probably worthwhile to use the column ordinals instead of the names to index into each DataRow by replacing the definitions of rc1 and rc2:
var rc1 = rtnCols1.Select(dc => dc.Ordinal).ToList();
var rc1Names = rtnCols1.Select(dc => dc.ColumnName).ToHashSet();
var rtnCols2 = dt2.Columns.Cast<DataColumn>().Where(dc => columns.Contains(dc.ColumnName) && !rc1Names.Contains(dc.ColumnName)).ToList();
var rc2 = rtnCols2.Select(dc => dc.Ordinal).ToList();

How to get exact match from data row using Sql query

Hello i've datarow (IDs) as
12?15?6?11?51?
1?15?6?11?51?
&
I want to search numbers which is equal to 1 (id). For That When i used
%1% this will return match result as both rows
%1?% this will return match result as both rows
%?1?% this will return match result as null
%?1% this will return match result as both rows
the result should be only 2nd row for ID 1.
Please give proper query for this.
Thanks.
SELECT * FROM TableName WHERE ID LIKE '1?%' OR ID LIKE '%?1?%'
SELECT * FROM TABLE WHERE ID LIKE '1?_%' ;
This will work meaning if you contain starting with 1?
You can use
CREATE TABLE T(
ID VARCHAR(45)
);
INSERT INTO T VALUES
('12?15?6?11?51?'),
('1?15?6?11?51? &');
SELECT *
FROM T
WHERE ID LIKE '[1][^0-9]%';
Returns:
+-----------------+
| ID |
+-----------------+
| 1?15?6?11?51? & |
+-----------------+
Demo

How to make UNION of 2 SELECT statement

This is my query:
string x1 = "SELECT unos_golub.drzava, unos_golub.spol, unos_golub.broj_goluba as broj, parovi.par_m, parovi.par_z,parovi.broj_para FROM parovi JOIN unos_golub ON (parovi.par_m=unos_golub.ID) WHERE parovi.uzgojni_par=1";
string x2 = "SELECT unos_golub.drzava, unos_golub.spol, unos_golub.broj_goluba as broj2, parovi.par_m, parovi.par_z,parovi.broj_para FROM parovi JOIN unos_golub ON (parovi.par_z=unos_golub.ID) WHERE parovi.uzgojni_par=1 ORDER BY broj_para ASC";
cmd.CommandText = x1+" UNION ALL "+x2;
In my table "parovi" there are 2 columns "par_m" and "par_z".
In second table "unos_golub" there is "ID" and some other. Now I need to get values from "par_m" and "par_z", match it in "unos_golub" and get some data.
For example, if I get par_m=91 and par_z=92, I need to find those numbers in ID of "unos_golub" and get different data for 91 and 92 and show it.
I think maybe UNION ALL could help, but it is not working.
here are my tables
table: parovi
table: unos_golub
This approach will put all on a single row for the respective "M" and "Z" values. Notice I'm joining TWICE to the "unos_golub" table, but with different aliases. So, now I have one parovi record pointing to respective "M" AND "Z" versions simultaneously. And can pull the columns from each, thus giving them aliased result column names suffixing "M" and "Z" indicating their respective origin.
SELECT
parovi.par_m,
parovi.par_z,
parovi.broj_para,
unos_M.drzava as drzava_M,
unos_M.spol as spol_M,
unos_M.broj_goluba as broj_M,
unos_Z.drzava as drzava_Z,
unos_Z.spol as spol_Z,
unos_Z.broj_goluba as broj_Z
FROM
parovi
JOIN unos_golub as unos_M
ON parovi.par_m = unos_M.ID
JOIN unos_golub as unos_Z
ON parovi.par_m = unos_Z.ID
WHERE
parovi.uzgojni_par=1";
Per your comment of wanting to show all rows, your query SHOULD only require one small change. When doing a UNION, the queries must have the same column names. You changed one o them via
unos_golub.broj_goluba as broj
vs
unos_golub.broj_goluba as broj2
which would make it fail the query. The column names are different, thus failing.

Column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

This may be a very silly mistake but I just can't fix it. I have 2 tables, Questions and Questions_Rating.
Questions:
question_id question user_id
------------------------------------------
1 'How to blablabla' 1
2 'bla bla bla' 1
Questions_Rating
In this table, users will rate questions either by +1 or -1
question_rating_id question_id user_id rate
------------------------------------------------------
1 1 2 (+1)
2 1 3 (+1)
3 1 4 ( 1)
Now I would simply like to fetch the question from the questions table, and the SUM of the rate in the questions_rating table for this question, which has an ID = 1.
String QUERY = "SELECT q.question, SUM(r.rate) FROM questions q, questions_rating r WHERE r.question_id = q.question_id AND q.question_id = 1";
And this is what I'm getting.
Column 'questions.question' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I know that the SUM of the rate will return 1 row, and the question is supposedly 1 row, I can't figure out what's wrong with this query.
I am using SQL Server 2008.
You will have to Group the values as per the question so you need a
GROUP BY q.question
at the end of your query
Good Explanation here
You need the group by q.question in your SQL statement.
Your Sum is suppose to return only a single row against the table, since you are selecting a column along with the Sum you need to specify a group on the selected column. In your case it should be q.question, and sum will be applied to each group of questions.
SELECT q.question,SUM(r.rate) AS RateSum
FROM questions q,questions_rating r
WHERE r.question_id = q.question_id AND q.question_id=1
GROUP BY q.question
or (using ANSI 92 style joins)
SELECT q.question,SUM(r.rate) AS RateSum
FROM questions q INNER JOIN questions_rating r ON r.question_id = q.question_id
WHERE q.question_id=1
GROUP BY q.question
or (using subqueries)
SELECT q.question, (SELECT SUM(r.rate) FROM questions_rating r WHERE r.question_id = q.question_id) AS RateSum
FROM questions q
WHERE q.question_id=1
You are missing group by clause in your select statement.
As you have used sum() function which is an aggregate function
So you need to write group by for all the select columns.
String QUERY = "SELECT
q.question,
SUM(r.rate)
FROM
questions q,
questions_rating r
where
r.question_id = q.question_id AND
q.question_id=1
group by
q.question";

How to Use 'IN' on a DataTable

I have this code in MS SQL:
select * from table where column1 in (select column2 from table)
How can I translate this using a DataTable?
Something along the lines of: table.select("column1 in column2")
you can't.
but you can do it via linq + table.select:
table.Select(string.Format("CITY in '{0}'",string.Join("','",table.Rows.OfType<DataRow>().Select(r=>r["COUNTRY"].ToString()).Distinct())))
EXPLANATION:
suppose you have a very simple table
ID CITY COUNTRY
1 NY USA
2 Moscow Russia
3 LA USA
4 St Peterburg Russia
Using LINQ to Objects we select all unique values from Country column and concatenate values (via string.Join) to the IN filter statement string. For our example it will be USA','Russia
surround IN filter statement with quotes via string.Format: 'USA','Russia'
Pass IN filter in dataTable.Select("CITY IN ('USA','Russia')")
FYI:
If you need to execute really cool SQL queries against DataTables\DataSets you can use NQuery it is very fast and standards compliant.
Assuming the tables are in the same DataSet, you can add a DataRelation to the DataSet and then access the child rows using GetChildRows()
var relation = new DataRelation("RelationName",
dataSet.Tables["Parent"].Columns["Column2"],
dataSet.Tables["Child"].Columns["Column1"]);
dataSet.Relations.Add(relation);
var childRows = from row in dataSet.Tables["Child"].Rows
where row.GetParentRows("RelationName").Length > 0;
You can use the following LINQ to DataSets query to get the same result as the query you have in SQL.
var rows = from r1 in table.AsEnumerable()
from r2 in table.AsEnumerable()
where r1.Field<string>("Column1") == r2.Field<string>("Column2")
select r1;
I assume from your example that the columns are coming from the same table. If not then you just need to change the table in the above as follows.
var rows = from r1 in table1.AsEnumerable()
from r2 in table2.AsEnumerable()
where r1.Field<string>("Column1") == r2.Field<string>("Column2")
select r1;
This is similar to
select * from table1 where column1 in (select column2 from table2)

Categories

Resources