Alphanumeric Sorting using SQL Server / C# [duplicate] - c#

This question already has answers here:
Natural (human alpha-numeric) sort in Microsoft SQL 2005
(14 answers)
Closed 5 years ago.
I have alphanumeric numbers. After applying sorting thru SQL Server ORDER BY clause, I get following result
select *
from WO
where WOCode = AnyNumber
order by [ColumnName]
Result:
39660A1
39660A10
39660A11
39660A2
39660A3
39660A4
39660A5
39660A6
39660A7
39660A8
39660A9
Required result
39660A1
39660A2
39660A3
39660A4
39660A5
39660A6
39660A7
39660A8
39660A9
39660A10
39660A11

Here is a quick and dirty solution:
SELECT *
FROM table
ORDER BY LEN(Field) ASC, Field ASC
Demo here.

Assuming that the letter A is always in the same position, and the characters after it are integers only.
Then you can do this:
WITH CTE AS
(
SELECT
WOCode,
CAST(SUBSTRING(WOCode, CHARINDEX('A', WOCode) + 1,
LEN(WOCode) - CHARINDEX('A', WOCode) + 1) AS INT) AS DisplayOrder
FROM
WO
)
SELECT *
FROM CTE
ORDER BY DisplayOrder;
Demo
Results:
| WOCode |
|----------|
| 39660A1 |
| 39660A2 |
| 39660A3 |
| 39660A4 |
| 39660A5 |
| 39660A6 |
| 39660A7 |
| 39660A8 |
| 39660A9 |
| 39660A10 |
| 39660A11 |
You can also use TRY_CAST to avoid errors that might result because of using cast with non integer values (Thanks to #zambonee for suggestion):
WITH CTE AS
(
SELECT
WOCode,
CASE
WHEN TRY_CAST(WOCode AS INT) IS NULL
THEN CAST(SUBSTRING(WOCode,
CHARINDEX('A', WOCode) + 1,
LEN(WOCode) - CHARINDEX('A', WOCode) + 1) AS INT)
ELSE 0
END AS DisplayOrder
FROM
WO
)
SELECT *
FROM CTE
ORDER BY DisplayOrder;
updated demo

Related

UnionBy() EF Core

I have this ef query that give me the following result
IQueryable<A>
| Id | count |
| 1 | 5 |
| 2 | 6 |
IQueryable<B>
| Id | count |
| 1 | 1 |
| 2 | 2 |
| 3 | 9 |
When I do
IQueryable<Something> C = A.union(B)
Result that I got is this
| Id | count |
| 1 | 5 |
| 2 | 6 |
| 1 | 1 |
| 2 | 2 |
| 3 | 9 |
Whish is logical.
What I want is a UnionBy(Id)
IQueryable<Something> C = A.unionBy(B,c=>c.Id)
and this work perfectly in my case
| Id | count |
| 1 | 5 | -- FROM A
| 2 | 6 | -- FROM A
| 3 | 9 | -- FROM B
If the Query A or B are already executed by that I mean a ToList() was made it work perfectly and I have no problem in anyway.
But in my case, both queries are not executed and thus using this function result in.
System.InvalidOperationException query could not be translated.
the alternative is to use a GroupBy however I have no idea how to replacte UnionBy behavior with the GroupBy
FYI: the query works perfectly using the IQueryable.Union
and it's mandatory in my case that the request stay in IQueryable and not executed until later
UPDATE
⚠️ The solution that I'm looking for must stay in IQueryable without a toList() execution
"query could not be translated" usually means that EF doesn't support a certain LINQ or language construct as it can't translate it into SQL. One way to make this work is to force the evaluation of the expression client-side by adding e.g. ToList() or likes on the query parts before executing the UnionBy:
IQueryable<Something> C = A.ToList().UnionBy(B.ToList(),c=>c.Id);
The solution is simple you filtre A From B using the following
IQueryable<Something> C = A.Union(B.where(b=> A.All(a=>a.Id != b.Id))

Remove the string after '-' and group remaining string and pivot column

Here is my actual data in Excel, which I am successfully able to read in DataGridView in C# Windows Application.
Test | Energy |
---------------------
C018-3L-1 | 113 |
C018-3L-2 | 79 |
C018-3L-3 | 89 |
C018-3L-4 | 90 |
C018-3L-5 | 95 |
C021-3T-1 | 115 |
C021-3T-2 | 100 |
But now I want this data in DataGridView in below Format from excel file:
Test |Energy-1|Energy-2|Energy-3 |
------------------------------------
C018-3L |113 |79 |89 |
C018-3L |90 |95 |NULL |
C021-3T |115 |100 |NULL |
Here is my code:
private void TensileEnergyData_Load(object sender, EventArgs e)
{
try
{
string sourcefilepath = ConfigurationManager.AppSettings["FilePath"].ToString();
string[] files = Directory.GetFiles(sourcefilepath, "*.xlsx");
foreach (string s in files)
{
string excelConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + s + ";Extended Properties='Excel 12.0;HDR=YES';";
// Create Connection to Excel Workbook
using (OleDbConnection connection = new OleDbConnection(excelConnectionString))
{
connection.Open();
da = new OleDbDataAdapter("Select Test, Energy FROM [Sheet1$]", connection);
da.Fill(dtExcelData);
connection.Close();
}
}
}
catch (Exception ex)
{
objDAL.SendExcepToDB(ex, "TensileEnergyData_Load");
MessageBox.Show("Fail to read data...!!");
}
dataGridView1.Visible = true;
dataGridView1.DataSource = dtExcelData;
}
How can I achieve this using Group By?
I'll provide a SQL-Server based answer, as your very related question asked for this. Here you did not tag your question with [sql-server] at all... Hope this helps...
This is a very good reason, why you should never ever put more than one content in one column. Store this in separate columns and this will be much easier.
Further more, this smells a bit... Such issues should rather be solved in your presentation layer.
Nevertheless this can be done:
DECLARE #tbl TABLE(Test VARCHAR(100),Energy INT);
INSERT INTO #tbl VALUES
('C018-3L-1',113)
,('C018-3L-2',79)
,('C018-3L-3',89)
,('C018-3L-4',90)
,('C018-3L-5',95)
,('C021-3T-1',115)
,('C021-3T-2',100);
SELECT p.*
FROM
(
SELECT B.Code
,(B.Number-1)/3 AS Line
,CONCAT('Energy-',CASE B.Number % 3 WHEN 0 THEN 3 ELSE B.Number % 3 END) AS ColumnName
,Energy
FROM #tbl t
CROSS APPLY(SELECT LEN(t.Test) - CHARINDEX('-',REVERSE(t.Test))) A(PosLastHyphen)
CROSS APPLY(SELECT LEFT(t.Test,PosLasthyphen) AS Code
,CAST(SUBSTRING(t.Test,PosLastHyphen+2,10) AS INT) AS Number) B
) tbl
PIVOT
(
MAX(Energy) FOR ColumnName IN([Energy-1],[Energy-2],[Energy-3])
) p
ORDER BY Code,Line;
The result
+---------+------+----------+----------+----------+
| Code | Line | Energy-1 | Energy-2 | Energy-3 |
+---------+------+----------+----------+----------+
| C018-3L | 0 | 113 | 79 | 89 |
+---------+------+----------+----------+----------+
| C018-3L | 1 | 90 | 95 | NULL |
+---------+------+----------+----------+----------+
| C021-3T | 0 | 115 | 100 | NULL |
+---------+------+----------+----------+----------+
Some explanations
I use the CROSS APPLY to compute the separation of your code and the running number. Then I use the integer division to calculate the group and the modulo operator % to spread this in three columns.

Linq : filter duplicated line without taking account a column [duplicate]

This question already has answers here:
LINQ's Distinct() on a particular property
(23 answers)
Closed 6 years ago.
I'm trying to remove from a datatable the duplicated lines, but without taking into account a column into the duplication filter.
Example :
| Name | Region |
| Toto | 5 |
| Toto | 2 |
| Toto | 1 |
| Gege | 2 |
What I'm searching for if to filter it as the following
| Name | Region |
| Toto | 5 |
| Gege | 2 |
Thank for your help.
Try this
var filteredData = data.GroupBy( d=> d.Name).SelectMany(grouping => grouping.First());
Depending upon LinqProvider for the database (IQueryable implementation), The query may run on database, or on client side( if so, there will be memory/network bandwidth issues).
In some case, not all Linq constructs are supported.
Try:
datatable.GroupBy(x => x.Name);
you need to add a using for the System.Linq namespace.

Possible to add two columns together and group by that column using linq on IQueryable?

My data comes from IQueryable that looks like the following table when I return all of the DailyCollectionActivities.
CatType | CdDescr | CollTypeDescr | RollCasteDescr | TIFDescr | TADescr | Amount
--------------------------------------------------------------------------------
Cat 1 | Cd 1 | CollType 233 | Roll Caste 234 | TIF 2344 | TA 2343 | 344.35
Cat 1 | Cd 1 | CollType 222 | Roll Caste 235 | TIF 2345 | TA 2344 | 355.35
Cat 2 | Cd 2 | CollType 223 | Roll Caste 236 | TIF 2346 | TA 2345 | 664.44
Cat 3 | Cd 3 | CollType 255 | Roll Caste 236 | TIF 2347 | TA 2346 | 455.34
Cat 4 | Cd 4 | CollType 266 | Roll Caste 236 | TIF 2348 | TA 2347 | 455.44
I'm trying to find out if it's possible, using linq on the IQueryable<DailyCollectionActivity> data, to add two columns together and then group on that newly created column? For example I need to figure out how to add CatType to CdDescr (CatType + '-' + CdDescr) and then group by that newly created column and sum the Amounts. Finally, I then need to take the results of that query and bind it to a RadGrid.
To make things more interesting, the user is allowed to choose which columns get added together. I could wind up with a group by clause like (CatType + '-' CdDescr), (TIFDescr + '-' + TADescr).
Is this something that I can reasonably accomplish using Linq?
say its from categories
var result = from s in (
from p in categories
select new {
TypeDesr = p.CatType+"-"+ p.CdDesr,
CollTypeDescr = p.CollTypeDescr ,
RollCasteDescr = p.RollCasteDescr,
TIFDescr = p.TIFDescr,
TADescr = p.TADescr,
Amount = p.Amount
})
group s by s.TypeDesr into r
select r;

Inserting/Updating rows with some columns and preserve values of others

A little background information: I have a table called table_a, which has 12 columns. I want to insert or update rows with values for 6 of these columns, while I don't wanna lose the data in the other 6 columns. And I wanna do this with a parameterized query in C#.
field1 is Unique.
> SELECT * FROM table_a;
+----+--------+--------+---+---------+---------+
| Id | field1*| field2 |...|field11 | field12 |
+----+--------+--------+---+---------+---------+
| 1 | AA | BB |...| KK | LL |
| 2 | AA | BB |...| KK | LL |
| 3 | AA | BB |...| KK | LL |
| 4 | AA | BB |...| KK | LL |
+----+--------+--------+---+---------+---------+
The Problem is, my first thought was to use REPLACE INTO, unfortunately this will delete the 6 not touched values:
> REPLACE INTO table_a (field1, ..., field6) VALUES ('AA', ...);
> REPLACE INTO table_a (field1, ..., field6) VALUES ('AB', ...);
+----+--------+--------+---+---------+---------+
| Id | field1*| field2 |...| field11 | field12 |
+----+--------+--------+---+---------+---------+
| 1 | AA | BB |...| NULL | NULL |
| 2 | AB | BB |...| NULL | NULL |
| 3 | AC | BB |...| KK | LL |
| 4 | AD | BB |...| KK | LL |
+----+--------+--------+---+---------+---------+
My second thought was to use INSERT INTO ... ON DUPLICATE KEY UPDATE, but then I'd have to bind the parameters a second time, the first time in the INSERT part and the second time in the UPDATE part, like this:
INSERT INTO table_a (field1, ..., field6)
VALUES(?, ..., ?)
ON DUPLICATE KEY UPDATE
field1 = ?, ..., field6 = ?;
That would preserve my data, but I have to bind the parameters twice.
The third option would be to create another two queries and use the SELECT and INSERT INTO/UPDATE pattern.
So, my question is, how do I do this the smart way?
Your second option sounds like a winner for single row updates.
Your third option is good if you insert/update many rows at once (as it will not matter much that you have two queries then - providing each does only what it is supposed to do).
UPDATE:
Digging through documentation one finds that you can bind once if you wish - you can refer to the originally bound values with VALUES()
UPDATE2:
Well, actually you can not get to the bound values with VALUES(column), so instead two suggestions that actually might help:
did you check about using named parameters (then you would not need to bound them twice)?
did you consider stored procedures?
I think you've listed all the available options, along with the pros/cons of each. As for the third option, you would probably want to wrap your two queries in a transaction to ensure that the operation remains atomic.
Hi let's say you want to modify field2 to field6.
why wouldn't you do:
replace into table_a select field1,new_value2,...,new_value6,field7,...,field12 from table_a where field1=filter_field1;
You put the new values and you get the others value by querying the table you're updating.

Categories

Resources