how to merge three rows into one row - sql

how to change output of the sql query from 1 to 2
1:- user_id subject name marks
1001 maths 67
1001 pyhsics 78
1001 chemistry 87
1002 maths 89
1002 physics 56
1002 chemistry 76
2:- user_id maths physics chemistry
1001 67 78 87
1002 89 56 76
I'm expecting sql query

Use crosstab (pivot tables) to turn rows into columns:
SELECT *
FROM crosstab(
'SELECT user_id, subject_name, marks FROM t'
) AS ct(user_id int, maths int, physics int, chemistry int);
Another option, with a slightly different purpose, is to use conditional aggregates with FILTER:
SELECT
user_id,
SUM(marks) FILTER (WHERE subject_name = 'maths') AS maths,
SUM(marks) FILTER (WHERE subject_name = 'physics') AS physics,
SUM(marks) FILTER (WHERE subject_name = 'chemistry') AS chemistry
FROM t
GROUP BY user_id;
Demo: db<>fiddle

Related

How to group by and rank in sql , then select other columns from table all rows for a particular group should be together

I want to group rows based on an id column and order by sum of an another column. Then I need these rows with all columns from table as ordered groups.
Here an example what I am trying to do:
SELECT Studentname,
Subject,
Marks,
RANK() OVER(PARTITION BY Studentname ORDER BY Marks DESC) Rank
FROM ExamResult order by Studentname
Result:
Studentname Subject Marks Rank
Isabella english 90 1
Isabella Science 70 2
Isabella Maths 50 3
Lily Science 80 1
Lily english 75 2
Lily Maths 65 3
Olivia english 95 1
Olivia Science 60 2
Olivia Maths 60 3
What i need is order by sum(marks) then group all records for that student as one entity. As here total marks for Isabella, Lily and Olivia are 210, 220 and 215.
So order for group should be Lily, Olivia, and Isabella.
required result:
Studentname Subject Marks Rank
Lily Science 80 1
Lily english 75 1
Lily Maths 65 1
Olivia english 95 2
Olivia Science 60 2
Olivia Maths 60 2
Isabella english 90 3
Isabella Science 70 3
Isabella Maths 50 3
You can use two levels of window functions:
SELECT Studentname, Subject, Marks,
RANK() OVER(PARTITION BY Studentname ORDER BY Sum_Marks DESC) Rank
FROM (SELECT er.*,
SUM(Marks) OVER (PARTITION BY StudentName) as sum_marks
FROM ExamResult
) er
ORDER BY Studentname

Split a column based on a character in BigQuery

I have a table as shown below on BigQuery
Name | Score
Tim | 63 > 89 > 90
James| 67 > 44
I want to split the Score column into N separate columns where N is the maximum score length in the entire table. I would like the table to be as follow.
Name| Score_1 | Score_2 | Score_3
Tim | 63 | 89 | 90
James| 67 | 44 | 0 or NA
I tried the Split command but I end up doing a new row for each Name-Score combination.
For BigQuery Standard SQL
Below is simple case and assumes you know in advance the expected max score length (3 in below example)
#standardSQL
WITH `project.dataset.your_table` AS (
SELECT 'Tim' name, '63 > 89 > 90' score UNION ALL
SELECT 'James', '67 > 44'
)
SELECT
name,
score[SAFE_OFFSET(0)] AS score_1,
score[SAFE_OFFSET(1)] AS score_2,
score[SAFE_OFFSET(2)] AS score_3
FROM (
SELECT name, SPLIT(score, ' > ') score
FROM `project.dataset.your_table`
)
with result
Row name score_1 score_2 score_3
1 Tim 63 89 90
2 James 67 44 null
Of course above approach means - if you have many scores - like 10 or 20 or more - you will need to add respective number of extra lines like below
score[SAFE_OFFSET(20)] AS score_21
So, above gives you what you wanted from schema of output point of view
At the same time, below makes more sense to me and in most practical cases is better and most optimal :
#standardSQL
WITH `project.dataset.your_table` AS (
SELECT 'Tim' name, '63 > 89 > 90' score UNION ALL
SELECT 'James', '67 > 44'
)
SELECT name, score
FROM `project.dataset.your_table`, UNNEST(SPLIT(score, ' > ')) score
with result
Row name score
1 Tim 63
2 Tim 89
3 Tim 90
4 James 67
5 James 44

order different columns into one order?

I have a table like this;
Student_Name1 mark1 Student_Name2 mark2
-------------- ------ --------------- --------
Kevin 77 Peter 78
Andrew 91 David 17
Scott 46 Bradley 28
How am i able to order mark1 and mark2 in the above table into descending order by including all the names and the points all together, like below?
Student_Name mark
-------------- ------
Andrew 91
Peter 78
Kevin 77
Scott 46
Bradley 28
David 17
I am using MSSQL Server 2008 R2
Use a UNION ALL:
Select Student_Name1 As Student_Name,
Mark1 As Mark
From YourTable
Union All
Select Student_Name2 As Student_Name,
Mark2 As Mark
From YourTable
Order By Mark Desc;
That's a strange table design but you can use UNION for this purpose like
select * from (
select Student_Name1 as Student_Name, mark1 as mark from student
union all
select Student_Name2 , mark2 from student ) xxx
order by mark desc;

How to convert Columns into Rows or Vica Versa

I have two tables
Student:
Name Class Maths Science English Hindi
Sonia 2 98 67 53 58
Vijay 7 89 68 45 51
Abhishek Mishra 6 87 89 52 53
Rupal 8 74 76 59 64
Gaurav 10 90 78 43 41
Subject:
Subject Total_Marks
Maths 100
Science 100
English 75
Hindi 75
When I select name sonia it should provide following SQL output:
Subject Total_Marks Obtained Marks
Maths 100 98
Science 100 67
English 75 53
Hindi 75 58
Okay, Without UNPIVOT you can achieve the desired result, like this -
DECLARE #subject table (subject varchar(10), total_marks int)
DECLARE #student table (name varchar(100),class int,maths int, science int,english int,hindi int)
INSERT INTO #subject
VALUES ('Maths', 100), ('Science', 100), ('English', 75), ('Hindi', 75)
INSERT INTO #student
VALUES ('sonia', 2, 98, 67, 53, 58),
('vijay', 7, 89, 68, 45, 51)
SELECT ri.subject, ri.total_marks, le.val as ObtainedMarks FROM
(
SELECT name, class, t.sub, t.val FROM #student
CROSS APPLY (VALUES ('maths', maths), ('science', science), ('english', english), ('hindi', hindi)) AS t(sub, val)
) le
INNER JOIN
(
SELECT * FROM #subject
) ri
ON le.sub = ri.subject
WHERE le.name = 'sonia'
Here i have used CROSS APPLY with VALUES clause to make key-value pair combination of subject name as key and its column value as value.
Result
subject total_marks ObtainedMarks
-------------------------------------
Maths 100 98
Science 100 67
English 75 53
Hindi 75 58
This reeks of a school problem, but giving you benefit of doubt, you should try UNPIVOT syntax rather than PIVOT syntax.
See MSDN documentation for both here
Using UNPIVOT followed by LEFT JOIN, the query should like below
select UP.Subject,Total_Marks, Obtained_Marks from
(
select
S.Name as Name,
S.Maths as Maths,
S.Science as Science,
S.English as English,
S.Hindi as Hindi
from Student S
where S.Name like 'sonia'
)source
UNPIVOT
(
Obtained_Marks for Subject in (Maths,Science, English, Hindi)
)UP
LEFT JOIN Subject S
ON S.Subject=UP.Subject
INSERT queries used for schema:
create table subject(subject varchar(10), total_marks int)
insert into subject values('Maths',100),('Science', 100),('English', 75),('Hindi', 75)
create table student(name varchar(100),class int,maths int, science int,english int,hindi int)
insert into student values
('sonia',2,98,67,53,58),
('vijay',7,89,68,45,51)

SQL Teradata query

I have a table abc which have many records with columns col1,col2,col3,
dept | name | marks |
science abc 50
science cvv 21
science cvv 22
maths def 60
maths abc 21
maths def 62
maths ddd 90
I need to order by dept and name with ranking as ddd- 1, cvv - 2, abc -3, else 4 then need to find out maximum mark of an individual. Expected result is
dept | name | marks |
science cvv 22
science abc 50
maths ddd 90
maths abc 21
maths def 62
. How may I do it.?
SELECT
dept,
name,
MAX(marks) AS mark
FROM
yourTable
GROUP BY
dept,
name
ORDER BY
CASE WHEN name = 'ddd' THEN 1
name = 'cvv' THEN 2
name = 'abc' THEN 3
ELSE 4 END
Or, preferably, have another table that includes the sorting order.
SELECT
yourTable.dept,
yourTable.name,
MAX(yourTable.marks) AS mark
FROM
yourTable
INNER JOIN
anotherTable
ON yourTable.name = anotherTable.name
GROUP BY
yourTable.dept,
youtTable.name
ORDER BY
anotherTable.sortingOrder
This should work:
SELECT Dept, Name, MAX(marks) AS mark
FROM yourTable
GROUP BY Dept, Name
ORDER BY CASE WHEN Name = 'ddd' THEN 1
WHEN Name = 'cvv' THEN 2
WHEN Name = 'ABC' THEN 3
ELSE 4 END