SELECT DISTINCT in DataView's RowFilter - c#

I'm trying to narrow down the rows that are in my DataView based on a relation with another table, and the RowFilter I'm using is as follows;
dv = new DataView(myDS.myTable,
"id IN (SELECT DISTINCT parentID FROM myOtherTable)",
"name asc",
DataViewRowState.CurrentRows);
"myTable" and "myOther" table are related via myTable.ID and myOtherTable.parentID, and so the idea is that the DataView should only contain rows from "myTable" which have corresponding child rows in "myOtherTable".
Unfortunately, I'm getting this error;
Syntax error: Missing operand after
'DISTINCT' operator.
The SQL is fine as far as I am aware, so I'm wondering is there some limitation on using the DISTINCT keyword as part of RowFilter's SQL? Anyone have any idea?

Unfortunately, I don't think you can perform a subquery in a DataView's filter expression. You're only allowed to use a subset of SQL in some expressions (documented here).
You'll probably need to perform your subquery (SELECT DISTINCT parentID FROM myOtherTable) separately.
This article describes the problem and a possible solution.

Unfortunately you can't do it that way, as the RowFilter property does not support the distinct keyword. Here is the list of expressions you can perform in a RowFilter (which is just a DataColumn Expression): http://msdn.microsoft.com/en-us/library/system.data.datacolumn.expression.aspx
DataViews have a ToTable method, and several overloads take a boolean to specify whether to return only the distinct rows.
Here is one method: http://msdn.microsoft.com/en-us/library/wec2b2e6.aspx
Here is how you would use it:
DataTable newDataTable = myDataView.ToTable( true, [array of column names as strings] );

DataView dvBindAssignedByDropDown = new DataView();
DataTable dtBindAssignedByDropDown = new DataTable();
dvBindAssignedByDropDown = ds.Tables[0].DefaultView;
string[] strColnames=new string[2];
strColnames[0] = "RedNames";
strColnames[1] = "RedValues";
dtBindAssignedByDropDown = dvBindAssignedByDropDown.ToTable(true, strColnames);
ddlAssignedby.DataTextField = "RedNamesNames";
ddlAssignedby.DataValueField = "RedNames";
ddlAssignedby.DataSource = dtBindAssignedByDropDown;
ddlAssignedby.DataBind();
ddlAssignedby.Items.Insert(0, "Assigned By");
ddlAssignedby.Items[0].Value = "0";

the following code is extracting distinct values/records from a table/dataview, namely(PROD_DESP_TRN) having field(CONTAINER_NO)
Finally, this code is filling a combobox(cmbContainerNo) with unique values/records
Form Level Declaration:
Dim dsLocal As DataSet
Dim dvm As DataViewManager
Private Sub FillcomboContainer()
Try
Dim dv As DataView = New DataView
cmbContainerNo.DataSource = Nothing
dv = dvm.CreateDataView(dsLocal.Tables("PROD_DESP_TRN"))
dv.Sort = "CONTAINER_NO"
cmbContainerNo.DataSource = dv.ToTable(True, "CONTAINER_NO")
cmbContainerNo.DisplayMember = "CONTAINER_NO"
Catch ex As Exception
MsgBox(ex.Message)
Finally
End Try
End Sub

Try just leaving out the "DISTINCT". In this case, the results should be the same with or without. Troubleshoot from there.

Related

How to use Not In datatable.select

I have a DataTable (Ado.Net) with column 'Status'. This column holds the values (in each records)
['Red','Green','Blue','Yellow','White','OtherColors']
I want to select all the rows which status value not Red,Green,Blue
What the kind of filter expression to use to select data with my proposed criteria. So i want to achive some thing like we used in sql query ( WHERE Status NOT IN ('Red','Green','Blue')
NB:This project is running .NET 2.0 i cant use linq
I have tested it, it works as desired:
DataRow[] filtered = tblStatus.Select("Status NOT IN ('Red','Green','Blue')");
The resulting DataRow[] contains only DataRows with OtherColors, Yellow and White.
If you could use LINQ i'd prefer that:
string[] excludeStatus = {"Red","Green","Blue"};
var filteredRows = tblStatus.AsEnumerable()
.Where(row => !excludeStatus.Contains(row.Field<string>("Status")));
Without Linq you can use the rowfilter of a DataView like this
public DataTable GetFilteredData(DataTable table, string[] filterValues)
{
var dv = new DataView(table);
var filter = string.join("','", filterValues);
dv.RowFilter = "Status NOT IN ('" + filter + "')";
return dv.ToTable();
}
Supposing your datatable is part of a typed dataset you can use Linq to datasets, from which you could something like:
var records =
from record in datatable
where !record.Status.Contains('Red','Green','Blue')
select record;
Even if you don't have a typed dataset Linq to datasets is your answer. You would need to some casting, but not to difficult.

Sort and Search Datatable

I have a datatable that has been bound to a Gridview in code behind. This means i would have to sort columns in code behind and when searching for a record i would imagine that would be done in code behind too.
The code i have to sort the gridview is
Private Function GetCustData As Datatable
Dim dt as new datatable
dt = GetDataFromBusinessLayer(CustomerID)
Return dt
End Function
And the code to sort
Private Sub gv_Sorting(sender As Object, e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles gv.Sorting
If e.SortExpression = "Name"
gv.DataSource = GetCustData '.DefaultView.Sort = "Name" & "DESC"
gv.DataBind()
End If
End Sub
As you can tell i tried using .DefaultView.Sort = "Name" & "DESC" but this didnt work and got the error Data source is an invalid type. It must be either an IListSource, IEnumerable, or IDataSource. Searching around most are using Viewstate but that doesnt seem applicable in my case.
Can anyone advise how i would sort one/multiple columns?
In addition i will like to have a textbox which will search for the Name column. I think the above should suffice when it comes to it but if not could someone put me on the right track so i can work towards that now rather than having to change what im doing at a later stage?
First of all, your current code does not have a space. To sort by Name DESC your Sort string would need to be: "Name DESC".
To set the Sort string to multiple columns, just add a comma between each one, like this:
Dim dt as new datatable = GetCustData(1)
dt.DefaultView.Sort = "Name DESC, FirstName ASC"
gv.DataSource = dt.DefaultView
gv.DataBind()
I think you can create a list of rows
List<DataRow> list = dt.AsEnumerable().ToList();
and then when you have a list you can now use sort
list.OrederBy(c=>c.///specific value in your list)
What about using Linq to do the sort for you.
Dim dt as new datatable
dt = From dr as Datarow in GetDataFromBusinessLayer(CustomerID)
Order by dr.item("First Sort field), dr.Item("Second Sort Field")
Select dr
Return dt
... I did this without the IDE, but that should do the trick, I believe.
Here's one exmaple online - Sorting DataTable with Linq
Hope this helps.

select query on dataset in winforms program throw me an error

i have dataset in my C# program and i try to run query
DataRow[] drTitles = dsConf.Tables[1].Select("Distinct SNum");
but i got error
Syntax error: Missing operand after 'SNum' operator
Select is for filtering
use to table in data view to get distinct row
Use this syntax
System.Data.DataView dv = new System.Data.DataView(dsConf.Tables[1]);
System.Data.DataTable dt = dv.ToTable(true,"SNum");
This Select is not equivalent to the select clause used in SQL. Here, the role of the Select method is to filter, so you need to specify a filter parameter, like "Name = 'Cindy'". Read more here.

How to pass DataTable.Select() result to a new DataTable?

I have a DataTable named dt2 with data. I am calling its Select method to get some specific rows.
DataRow[] foundRows;
expression = "parent_id=1";
foundRows = dt2.Select(expression);
How can I pass the Select-method result to a new DataTable – say FilteredData?
You can use CopyToDataTable, available on IEnumerable<DataRow> types.
var filteredData = dt2.Select(expression).CopyToDataTable();
Just for clarity, the Select method returns an array of type DataRow. That's why we need to use CopyToDataTable(). Alex's answer is good. However, if the Select didn't return any rows, CopyToDataTable() will throw an InvalidOperationException.
So test that there is at least one DataRow before using the CopyToDataTable().
var filteredDataRows = dt2.Select(expression);
var filteredDataTable = new DataTable();
if(filteredDataRows.Length != 0)
filteredDataTable = filteredDataRows.CopyToDataTable();
Why not use a DataView instead?
DataView view = new DataView(dt2);
view.RowFilter = "parent_id = 1";
DataView will behave in very much the same way that a DataTable would with the added benefit that any change(s) to the underlying DataTable (dt2 in this case) would be automatically reflected in the DataView.

extract data from a dataset

I have a dataset that gets populated from a stored proc in sql server. I have a column that has lets say has a set of values. I do not know what those values are. All I know is that they of the type "string". I want to extract all the distinct values from that column.
You can use a DataView and set its RowFilter to the desired condition:
var view = new DataView(dataset.Tables["Table"]);
view.RowFilter = "Column = 42";
UPDATE: based on your updated question, you can use LINQ:
var table = dataset.Tables["Table"].AsEnumerable();
var distinctValuesForColumn =
table.Select(row => (string)row["Column"]).Distinct();
You can simply use Select method of the DataTable :
DataRow[] extractedRows =
yourDataSet.Tables["YourTableName"].Select("YourColumnName = 123");
You can also use Linq to query your datatables. Here is a link to some examples on the MS site - http://msdn.microsoft.com/en-us/vbasic/bb688086.aspx
I hope below statement will serve your purpose
ds.Tables["TableName"].DefaultView.ToTable( true, "columnName"); //For Dataset (true means distinct)
OR
`ds.Tables[0].DefaultView.ToTable( true, "columnName");
//For Dataset where tableindex is 0
OR
dt.DefaultView.ToTable( true, "columnName"); //For Datatable
//Syntax is like Datatable.DefaultView.ToTable( Distinct true/false, “ColumnName”);
MSDN : http://msdn.microsoft.com/en-us/library/wec2b2e6.aspx

Categories