I am still new to LINQ and trying to convert this SQL command
Id | TitleName
------ | ------
1 | Accounts
2 | Buyer
3 | Engineer
4 | Other
5 | Apple
SELECT Id, TitleName
FROM dbo.Title
ORDER BY
CASE WHEN TitleName = 'Other'
THEN 0 ELSE 1 END DESC, TitleName ASC
This selects the table and ascends it in alphabetical order
Then it grabs 'Other' and forces it to the bottom.
So it ends up like this
Id | TitleName
------ | ------
1 | Accounts
5 | Apple
2 | Buyer
3 | Engineer
4 | Other
This works in SQL,
What is the best approach to achieve this using LINQ ?
Edit: Issue Resolved
var queryAllCustomerTitle = from cust in _titleRepository.Table
orderby cust.TitleName == "Other" ? 1 : 0, cust.TitleName
select cust;
use the ternary operator
OrderByDescending(a=>a.TitleName == "Other" ? 0:1).ThenBy(a=>a.TitleName)
Related
I have a table tbTest like this:
q1 | q2 | q3 | type
--------------------
2 | 1 | 3 | student
3 | 2 | 1 | alumni
2 | 1 | 3 | alumni
1 | 1 | 3 | student
Now I want a new table which is based on the first table and finds the sum of every question by GroupWise convert it into like this:
q | student | alumni
---------------------
q1 | 3 | 5
q2 | 2 | 3
q3 | 6 | 3
SELECT Student,
Alumni
FROM
(SELECT q1, userType FROM tbTest2) tb1
PIVOT
(
SUM(q1)
FOR userType IN (Student, Alumni)
) AS tb2;
But using(above SQL) Pivot I can manage only one row like this:
student | alumni
---------------------
3 | 5
You can unpivot the data and aggregate. Based on the C# tag, I am assuming the database is SQL Server, in which case you can use apply:
select v.question,
sum(case when t.type = 'student' then val else 0 end) as student,
sum(case when t.type = 'alumni' then val else 0 end) as alumni
from t cross apply
(values ('q1', t.q1), ('q2', t.q2), ('q3', t.q3)) v(question, val)
group by v.question;
In other database, you can do something similar using a lateral join or union all.
I need to concatenate multiple columns values to single value (separated with coma for example). I can do it by string_agg(u.name, ',') as Users in PostgreSql. I tried do it in linq query syntax but I failed - all time I just get list with split values instead of one row with values concatenated in one field.
Let's assume that I have only three tables:
Doc User Doc_User
+----+--------------------+ +----+-----------+ +----+-----------+
| Id | Path | | Id | Name | | DocId | UserId |
+----+--------------------+ +----+-----------+ +----+-----------+
| 1 | "C:\\Files\\A.txt" | | 1 | "Adam" | | 1 | 1 |
| 2 | "C:\\Files\\B.txt" | | 2 | "Benny" | | 1 | 2 |
| 3 | "C:\\Files\\C.txt" | | 3 | "Charlie" | | 2 | 1 |
+----+--------------------+ +----+-----------+ | 2 | 2 |
| 2 | 3 |
+-------+--------+
At the start I was trying simple join:
var model = (from d in db.Docs
join du in db.DU on d.Id equals du.DocId
join u in db.Users on du.UserId equals u.Id
select new DataModel() { DocPath = d.Path, UserName = u.Name }).ToList();
As I suspected I got list with separated rows:
C:\Files\A.txt | Adam
C:\Files\A.txt | Benny
C:\Files\B.txt | Adam
C:\Files\B.txt | Benny
C:\Files\B.txt | Charlie
But what I want to obtain is:
C:\Files\A.txt | Adam, Benny
C:\Files\B.txt | Adam, Benny, Charlie
string.Join() is not recognized by EF and I can't use it in linq queries, Aggregate() not working too. How can I achieve this?
I've prepared example for play with it: .Net Fiddle.
The code below groups the common documents by path using LINQ and then joins the grouped document's UserNames, using string.Join. I also think you don't need ToList() in this line select new DataModel() { DocPath = d.Path, UserName = u.Name }).ToList(); if you are going to use this solution because we are going to use LINQ again.
var grouped = model.GroupBy(x => x.DocPath);
foreach (var iGrouped in grouped){
string.Join(",",iGrouped.Select(x => x.UserName));
Console.WriteLine(iGrouped.Key + " | " + string.Join(",",iGrouped.Select(x => x.UserName)));
}
I have multiple tables and i have a search ASP.NET page with a GridView for the results.
The GridView must contain Name, School, State, Country
I have multiple tables that only contains the data:
index_States
indexID| State
----------------
1 | state1
2 | state2
3 | state3
index_Contries
indexID| Country
----------------
1 | country1
2 | country2
3 | country3
index_Schools
indexID| School
----------------
1 | school1
2 | school2
3 | school3
Then i have the tables that contains the indexID as reference
General_Info
idKey | Name
--------------
1 | John
2 | McClane
3 | Jr.
Academic_XP
id | idSchool | idState | idCountry | idKey
--------------------------------------------
1 | 1 | 3 | 20 | 2
2 | 1 | 5 | 146 | 3
3 | 2 | 1 | 65 | 9
And THEN I have the table that contains UserType as only certain type of user will be searched
Users
id | UserType | idKey
-----------------------
1 | 1 | 1
2 | 3 | 2
3 | 3 | 3
4 | 1 | 4
I've already tried multiple queries but none seem to be working.
Last query that seem to be working was with INNER JOIN
SELECT Name, State
FROM General_Info A, Academic_XP B
INNER JOIN index_States D ON B.idState = D.indexID
GROUP BY A.id;
but it doesn't work as soon as I add a second INNER JOIN or a WHERE clause.
SELECT Name, State
FROM General_Info A, Academic_XP B, Users
INNER JOIN index_States D ON B.idState = D.indexID
INNER JOIN index_School E ON B.idSchool = E.indexID
GROUP BY A.id
WHERE Users.UserType = 3;
I don't know how can I do that.
So i guess the question is
How can I made a query that returns from all those tables something like this?
Name | State | School | Country
---------------------------------------
McClane | state3 | school1 | country20
Jr. | state1 | school5 | country146
Note that McClane and Jr. are both UserType 3.
I will appreciate any help.
You are producing a cartesian product between tables without joins. I think this is what you're looking for using additional JOINs:
SELECT DISTINCT
G.Name,
S.State,
C.Country,
SC.School
FROM Academic_XP A
JOIN Users U ON A.idKey = U.idKey
JOIN General_Info G ON A.id = G.idKey
JOIN Index_States S ON A.idState = S.indexID
JOIN Index_Contries C ON A.idCountry = C.indexID
JOIN Index_Schools SC ON A.idSchool = SC.indexID
WHERE U.UserType = 3
If some tables don't have matching keys, you'll need to use an OUTER JOIN.
A Visual Explanation of SQL Joins
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
Here is my problem. i have 3-5 persons that is going to set a grade on one person and they use their own individual row to do so, and what I'm having trouble to do is to sum and average the grade from individual data across multiple rows on the same table.
in the select new statement i have made a pseudo answer of what i want
var users = from workRew in db.Reviews
select new
{
UserID = workRew.UserID.DistinctOfSomeSort
AvgGrade = workRew.Grade.Sum/CountOfSomeSort
};
Here i a illustration.
So if i have this table
| SomeID | UserID | Grade |
| 1 | 2 | 3 |
| 2 | 3 | 1 |
| 3 | 2 | 1 |
And this is the output i want from the LINQ query on the above (In theory ateast)
| UserID | AvgGrade |
| 2 | 2 |
| 3 | 1 |
EDIT: Simplified the whole case, to a great extent.
It should look something like this fragment:
group by user.UserID
select new
{
User = user.UserID
TotGradeCount = workRew.Grade.Sum()
Graders = workRew.Grade.Count()
}