Remove DataColumn from DataTable with Data - c#

I have Datatable with Data. I called my postgres data base and get DataTable.
// get the new data from postgres
var dataTable = pg.GetDataTable("SELECT * FROM " + '"'+table+'"');
Now I need to remove specific Column. assume that there are 5 columns with data.
ID | Name | Address | Mobile | Home
_______________________________________________
1 | A |AAA | 123 | 345
2 | B |BBB | 234 | 456
3 | C |CCC | 345 | 567
So I need to remove "Home " DataColumn and Recreate this DataTable as following
ID | Name | Address | Mobile
____________________________________
1 | A |AAA | 123
2 | B |BBB | 234
3 | C |CCC | 345
How can I do this ?
Appreciate your comments.
Thanks

Just specify the columns you need explicitly rather than selecting unneeded columns and removing them afterwards:
SELECT "Id", "Name", "Address", "Mobile"
Using SELECT * is bad manners because it makes your contract with database unstable - should column configuration change you will get unpredictable result.

You just need to use the method DataTable.Columns.Remove(string name):
dataTable.Columns.Remove("Home");
Then the table doesn't contain this column anymore and all rows' data in this column is thrown away. However, omit this column in the first place and list the desired columns:
var dataTable = pg.GetDataTable("SELECT ID, Name, Address, Mobile FROM " + '"'+ table +'"');

Consider using
dataTable.Columns.Remove("ColumnName")
or
dataTable.Columns.RemoveAt(ColumnNumber)

Related

Select row based on dynmically created value

I have a sql table below, value of column parameter and parameter value are dynamically created. The design below is cater for additional parameter being added in later stage. So I think using the parameter and parameter value as column is not ideal for such design.
|---------------------|------------------|------------------|
| Parameter | Parameter Value | Computers |
|---------------------|------------------|------------------|
| Phase | New | PC1 |
|---------------------|------------------|------------------|
| Phase | New | PC2 |
|---------------------|------------------|------------------|
| Phase | Redevelopment | PC3 |
|---------------------|------------------|------------------|
| Cost | High | PC1 |
|---------------------|------------------|------------------|
| Cost | High | PC2 |
|---------------------|------------------|------------------|
| Cost | Cost | PC3 |
|---------------------|------------------|------------------|
Given a scenario where a user search by Phase = "New" AND Cost = "High", it will result in PC1.
At this moment, I could think of is this:
SELECT *
FROM projectParameter
WHERE Parameter = 'Phase' AND Value = 'New' AND Parameter = 'Cost' AND Value = 'High'
Thanks in advance!
First, select all rows that match any part of your filtering.
Then aggregate all those rows to get one result per computer.
Then check each result to see if it contains all the required filtering contraints.
SELECT
Computers
FROM
yourTable
WHERE
(Parameter = 'Phase' AND ParameterValue = 'New')
OR
(Parameter = 'Cost' AND ParameterValue = 'High')
GROUP BY
Computers
HAVING
COUNT(*) = 2
From what I understand, it seems you want list of all computers where there is computer entry for both below conditions :
Parameter = 'Cost' AND Parameter Value = 'High'
Parameter = 'Phase' AND Parameter Value = 'New'
You can try below sql query to see it results your need :
SELECT t.computer
FROM table t
WHERE t.parameter = 'cost'
AND t.parameter_value = 'high'
AND EXISTS (
SELECT computer FROM table where computer=t.computer AND parameter = 'phase' AND parameter_value = 'new');

C# WPF DataGrid Group view of related tables

I have my data arranged in two related tables (SQLite). Let's say table Families and People. Table structure looks like below.
CREATE TABLE families (
FamilyID INTEGER PRIMARY KEY AUTOINCREMENT,
FamilyName VARCHAR,
FamilyPower INTEGER,
FamilyStatus Boolean
);
CREATE TABLE people (
PersonID INTEGER PRIMARY KEY AUTOINCREMENT,
FamilyID INTEGER REFERENCES families (FamilyID),
Name Varchar,
Age INTEGER
);
I'd like to display data from this table in grouped DataGrid. I can arrange this data as a DataSet, or as a custom class'es Objects or a netsted Objects (people could be a list of objects of class Person inside of the Family object). But I'm not sure which option is the best.
The worst option (I think) is doing one DataTable containing joined tables like SELECT * FROM families LEFT JOIN people ON families.FamilyID = people.PersonID. But I may be wrong and this is actually the best option to achieve what i want.
What I want is to display grouped data with group header containing full info about family and all its member as a data rows. So it would looks like below:
PersonID | Name | Age |
FamilyID: 1 Name: Stark Power: 10 Members: 3 Status: [x] <-- This is checkbox
1 | Eddard | 60 |
2 | Robb | 30 |
3 | Arya | 15 |
FamilyID: 2 Name: Lannister Power: 15 Members: 4 Status: [x]
4 | Cersei | 30 |
5 | Tyrion | 35 |
6 | Jaimie | 30 |
7 | Tywin | 30 |
FamilyID: 1 Name: Targaryen Power: 10 Members: 1 Status: [ ]
1 | Daenerys | 30 |
Is it even possible to achieve that? Please help me to choose best way to store data and solve how to bind and group it in the DataGrid?

Copy contents of one table to another table in a different Database

I have a SQL table similar to (call it UserTable)
+--------+-----------+----------+
| UserId | FirstName | LastName |
+--------+-----------+----------+
| 123 | Bob | Smith |
| 456 | John | Doe |
+--------+-----------+----------+
On a different server I have a table (call it UserBackupTable)
+----------+--------+-----------+----------+
| Location | UserId | FirstName | LastName |
+----------+--------+-----------+----------+
| A | 123 | Bob | Smith |
| B | 456 | John | Doe |
+----------+--------+-----------+----------+
The two tables are identical except for the addition of one column (Location). I would like to backup/copy UserTable to UserBackupTable in a better way than
var dataToCopy = userDb.UserTable.Select(user => new UserBackup
{
Location = _location,
FirstName = user.FirstName,
LastName = user.LastName
}).ToList();
backupDb.UserBackups.AddRange(dataToCopy);
This works but isn't very efficient for me when I have 40+ columns to have to manually type out. These are database first models in case that is needed.
Can you not just do this at the database layer, rather than via an ORM, e.g.
SELECT *
INTO [backupDb].[dbo].[UserBackups]
FROM [dbo].[UserTable]
You'll need to modify the above depending how you do it, e.g. incrementally, or recreating the whole backup table each time depending on the size of your data (just make sure you drop the existing table and select into its replacement as part of a transaction) but you could just automate it via SQL Server Agent or something.
Note that SELECT INTO creates a new target table, so that wouldn't be suitable for an incremental backup approach.

Linq syntax to find subtotal of grouped rows in a DataTable and update the DataTable

I have been scratching my head about this one... I have a table in memory, a DataTable structured like this:
Input:
ID | Invoice | Account | Payment | Subtotal
-----------------------------------------------------------------
0 | 09310 | 123 | 6.0 | ?
-----------------------------------------------------------------
And I wish to use Linq to perform the following (I am pretty new to Linq!)
For each row that is for the same account, add together all the payments and write or update the subtotal field(s)
I do not want to collapse the table, the invoice numbers are going to be different. My thought is that there are two ways that this can be done
(A) start with a BLANK subtotal column for all records... the values from payment would be added together and then written into the subtotal column
(B) when table created, I DUPLICATE the payment values into the subtotal fields. Later, the linq would only have to add/replace the values in the same column
So we would ignore the ID and Invoice fields; its ACCOUNT and SUBTOTAL (and PAYMENT as well if using style (A))
(A) Input: *(note that there are two records for 123)*
ID | Invoice | Account | Payment | Subtotal
-----------------------------------------------------------------
0 | 03310 | 123 | 6.0 |
-----------------------------------------------------------------
1 | 09728 | 123 | 4.0 |
-----------------------------------------------------------------
2 | 07731 | 559 | 18.0 |
-----------------------------------------------------------------
 
(B) Input:
ID | Invoice | Account | Payment | Subtotal
-----------------------------------------------------------------
0 | 03310 | 123 | 6.0 | 6.0
-----------------------------------------------------------------
1 | 09728 | 123 | 4.0 | 4.0
-----------------------------------------------------------------
2 | 07731 | 559 | 18.0 | 18.0
-----------------------------------------------------------------
 
Result:
ID | Invoice | Account | Payment | Subtotal
-----------------------------------------------------------------
0 | 03310 | 123 | 6.0 | 10.0
-----------------------------------------------------------------
1 | 09728 | 123 | 4.0 | 10.0
-----------------------------------------------------------------
2 | 07731 | 559 | 18.0 | 18.0
-----------------------------------------------------------------
And so, each Subtotal cell would have the total of all PAYMENTS for each unique ACCOUNT
I am thinking that style (B) would be easier because we only have to deal with those two columns
For style (B), I have tried something like
rpTable.AsEnumerable().GroupBy(g => int.Parse(g.Field<string>("Account"))).Select(g => g.Sum(p => p.Field<decimal>("SubTotal")));
but I can tell its missing something.....hmmmm
By using Select, you will not update the table. This just returns an IEnumerable of the selected values.
What you want to do is add the column to the table and then fill it:
var subTotalByAccount = table.AsEnumerable()
.GroupBy(g => g.Field<string>("Account"))
.Select(g => new { Account = g.Key, SubTotal = g.Sum(p => p.Field<decimal>("Payment")) })
.ToDictionary(t => t.Account, t => t.SubTotal);
table.Columns.Add("SubTotal", typeof(decimal));
foreach (var row in table.AsEnumerable())
{
row.SetField(columnName: "SubTotal", value: subTotalByAccount[row.Field<string>("Account")]);
}
Thank you very much timcbaoth, yes I agree with what you said. I tried to upvote your post but the system says I may not :-(
I had figured it out (below) using brute force, but I will evaluate your solution as well! Thanks again!!
var query = from row in rpTable.AsEnumerable()
group row by int.Parse(row.Field<string>("Account")) into grp
orderby grp.Key
select new
{
Id = grp.Key,
Sum = grp.Sum(r => r.Field<decimal>("Payment"))
};
foreach (var grp in query)
{
rpTable.Select("Account ="+grp.Id).ToList<DataRow>().ForEach(r=>r["Payment"] = grp.Sum);
}
I found an insidious little bug, so FYI:
OLD: rpTable.Select("Account ="+grp.Id).ToList<DataRow>().ForEach(r=>r["Payment"] = grp.Sum);
NEW: rpTable.Select("Account ='"+ grp.Id +"'").ToList<DataRow>().ForEach(r => r["Payment"] = grp.Sum);

How do a make a query to count which string appears the most in a certain column?

I'm making a program and I need to make a query to the database asking for the string that appears most often in a given column. In this example, its "stringONE".
----------------------------
| ID | Column (string) |
----------------------------
| 1 | stringONE |
----------------------------
| 2 | stringTWO |
----------------------------
| 3 | stringONE |
----------------------------
| 4 | stringONE |
----------------------------
Now I need to take the name of the string that appears the most and put it into a variable string, for example:
string most_appeared_string = sql.ExecuteScalar();
Also, what happens if there is no string that appears the most, rather 2 or more strings that appear the same amount of times, like this:
----------------------------
| ID | Column (string) |
----------------------------
| 1 | stringONE |
----------------------------
| 2 | stringTWO |
----------------------------
| 3 | stringTWO |
----------------------------
| 4 | stringONE |
----------------------------
Thanks ahead.
#KeithS
Do you have an sql-server version of the query because I'm getting some errors when trying it there. Here's a table example of what I'd like to do precisely.
------------------------------------------------
| ID | column1 (string) | author (string) |
------------------------------------------------
| 1 | string-ONE | John |
------------------------------------------------
| 2 | string-TWO | John |
------------------------------------------------
| 3 | string-ONE | Martin |
------------------------------------------------
| 4 | string-ONE | John |
------------------------------------------------
SELECT TOP (1) column1, COUNT(*) FROM table WHERE author='John' ORDER BY ID
It should return "string-ONE" since it appears the most (2) times for the author John. When trying the query in MS-SQL Management Studio though, this is the error I'm getting:
Column 'table.column1' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Nevermind the edit. Thank you.
This is a pretty easy query (in T-SQL at least):
select top 1 Column, Count(*) from Table group by Column order by Count(*) desc
ExecuteScalar, by an implementation detail, will return the string value because it's the first column of the only row in the result set, even though there are two columns. You could also use ExecuteReader to access the number of times that string occurs.
select top (1) SomeCol, count(*) as Row_Count
from YourTable
group by SomeCol
order by Row_Count desc
Also, what happens if there is no string that appears the most, rather
2 or more strings that appear the same amount of times, like this:
In that case, using the above query, you will get one arbitrary row. You can add with ties to get all rows that has the same highest value.
select top (1) with ties SomeCol, count(*) as Row_Count
from YourTable
group by SomeCol
order by Row_Count desc
SELECT max(counted) AS max_counted FROM (
SELECT count(*) AS counted FROM counter GROUP BY date
)
This could do the trick

Categories

Resources