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.
Related
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)
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
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()
}
On MS access, how to get the "ID" of the records having duplicate content on the "myData" column ?
something like :
---------------------- ------------------------
ID | myData | | ID | myData |
---------------------- ------------------------
1 | AAA | | 1 | AAA |
---------------------- ------------------------
2 | BBB | | 5 | AAA |
---------------------- ==> ------------------------
3 | CCC | | 2 | BBB |
---------------------- ------------------------
4 | BBB | | 4 | BBB |
---------------------- ------------------------
5 | AAA |
----------------------
All I can do so far do is this query:
SELECT myData, COUNT(myData) AS Expr1
FROM fooDB
GROUP BY myData
HAVING (COUNT(myData) > 1)
which only returns a list of the duplicates records from "mydata" and the number of occurrences, adding anything else will fail at execute. (and no ID's)
OR
Saying I accessing the DB as a DataTable in C#, how to manage this? Especially when this table has ~2000 records.
( maybe some help on how to work with INTERSECT to let it return the full rows having duplicates on one column )
Thanks.
SELECT ID, fooDB.myData
FROM (
SELECT myData
FROM fooDB
GROUP BY myData
HAVING COUNT(myData) > 1
) t INNER JOIN fooDB ON (t.myData = fooDB.myData)
I don't know if you can do a subquery in Access like this, but here's a typical SQL way to do it:
SELECT
id,
my_data
FROM
My_Table
WHERE
my_data IN
(
SELECT
my_data
FROM
My_Table
GROUP BY
my_data
HAVING
COUNT(*) > 1
)
Just throwing this out there...
SELECT distinct
f.ID,
f.myData
FROM
fooDB f
inner join fooDB f2 on f.myData = f2.myData
and f.ID <> f2.ID
Try
SELECT ID
FROM fooDB
WHERE myData IN (SELECT myData
FROM (SELECT myData, COUNT(myData) AS ROW_COUNT
FROM fooDB
GROUP BY myData)
WHERE ROW_COUNT > 1)
Share and enjoy.
I have a database where I store objects. I have the following (simplified) schema
CREATE TABLE MyObjects
(
UniqueIdentifier Id;
BigInt GenerationId;
BigInt Value;
Bit DeleteAction;
)
Each object has a unique identifier ("Id"), and a (set of) property ("Value"). Each time the value of the property for an object is changed, I enter a new row into this table with a new generation id ("GenerationId", which is monotonically increasing). If an object is deleted, then I record this fact by setting the "DeleteAction" bit to true.
At any point in time (generation), I would like to retrieve the state of all of my active objects!
Here's an example:
Id GenerationId Value DeleteAction
1 1 99 false
2 1 88 false
1 2 77 false
2 3 88 true
Objects in generations are:
1: 1 {99}, 2 {88}
2: 1 {77}, 2 {88}
3: 1 {77}
The key is: how can I find out the row for each unique object who's generation id is closest (but not exceeding) to a given generation id? I can then do a post-filter step to remove all rows where the DeleteAction field is true.
This works in MS SQL
SELECT id,value
FROM Myobjects
INNER JOIN (
SELECT id, max(GenerationID) as LastGen
FROM MyObjects
WHERE GenerationID <= #Wantedgeneration
Group by ID)
On GenerationID = LastGen
WHERE DelectedAction = false
My version uses a joint of the table MyObjects against a
subset of itself, created by a subquery, and containing only the last
generation for each object:
SELECT O.id,generation,value FROM
MyObjects O,
(SELECT id,max(generation) AS max_generation FROM MyObjects
WHERE generation <= $GENERATION_ID GROUP BY id) AS TheMax WHERE
TheMax.max_generation = generation AND O.deleted is False
ORDER BY generation DESC;
In the above query, the GENERATION_ID is hardwired. A way to
parametrize it is to write a function:
CREATE OR REPLACE FUNCTION generation_objects(INTEGER) RETURNS SETOF MyObjects AS
'SELECT O.id,generation,value,deleted FROM
MyObjects O,
(SELECT id,max(generation) AS max_generation FROM MyObjects
WHERE generation <= $1 GROUP BY id) AS TheMax WHERE
TheMax.max_generation = generation AND O.deleted is False;'
LANGUAGE SQL;
Now, it works. With this table:
> SELECT * FROM MyObjects;
id | generation | value | deleted
----+------------+-------+---------
1 | 1 | 99 | f
2 | 2 | 88 | f
1 | 3 | 77 | f
2 | 4 | 88 | t
3 | 5 | 33 | f
4 | 6 | 22 | f
3 | 7 | 11 | f
2 | 8 | 11 | f
I get:
> SELECT * FROM generation_objects(1) ORDER by generation DESC;
id | generation | value | deleted
----+------------+-------+---------
1 | 1 | 99 | f
> SELECT * FROM generation_objects(2) ORDER by generation DESC;
id | generation | value | deleted
----+------------+-------+---------
2 | 2 | 88 | f
1 | 1 | 99 | f
> SELECT * FROM generation_objects(3) ORDER by generation DESC;
id | generation | value | deleted
----+------------+-------+---------
1 | 3 | 77 | f
2 | 2 | 88 | f
And then, at the following generation, object 2 is deleted:
> SELECT * FROM generation_objects(4) ORDER by generation DESC;
id | generation | value | deleted
----+------------+-------+---------
1 | 3 | 77 | f
Here's the working version:
SELECT MyObjects.Id,Value
FROM Myobjects
INNER JOIN
(
SELECT Id, max(GenerationId) as LastGen
FROM MyObjects
WHERE GenerationId <= #TargetGeneration
Group by Id
) T1
ON MyObjects.Id = T1.Id AND MyObjects.GenerationId = LastGen
WHERE DeleteAction = 'False'
Not sure whether that's standard SQL, but in Postgres, you can use the LIMIT flag:
select GenerationId,Value,DeleteAction from MyObjects
where Id=1 and GenerationId < 3
order by GenerationId
limit 1;