I have a table tbl_Marks:
Std_id | sub_id | term_I | term_2
--------+---------+-----------+-------
std_1 | 1 | 40 | 50
std_1 | 2 | 30 | 40
std_1 | 3 | 20 | 30
std_1 | 4 | 10 | 50
std_2 | 1 | 50 | 50
std_2 | 2 | 50 | 50
std_2 | 3 | 50 | 50
std_2 | 4 | 50 | 50
How can I get result like this:
Std_id | sub_id | term_I | term_2 | total | status | PROMOTION_status
--------+---------+-----------+--------+--------+--------+------------------
std_1 | 1 | 40 | 50 | 90 | PASS | REPEATER
std_1 | 2 | 30 | 40 | 70 | PASS | REPEATER
std_1 | 3 | 20 | 20 | 40 | FAIL | REPEATER
std_1 | 4 | 10 | 50 | 60 | PASS | REPEATER
Note : if total value is less than 50 of any sub_id
std_2 | 1 | 50 | 50 | 100 | PASS | PROMOTED
std_2 | 2 | 50 | 50 | 100 | PASS | PROMOTED
std_2 | 3 | 50 | 50 | 100 | PASS | PROMOTED
std_2 | 4 | 50 | 50 | 100 | PASS | PROMOTED
Note: if total value is greater than 50 or equal of each sub_id
Please help!
Use CASE.
select t.*,
t.term_I + t.term_2 as total,
case when t.term_I + t.term_2 >= 50 then 'pass' else 'fail' end as status,
case when t.std_id = 'std_2' then 'PRMOTED' else 'REAPEATER' end as promotion_status
from tbl_marks t
Following SQL Select statement can help
Instead of SQL CTE expression you can also use subselect statements
But the main trick in this query is using MIN aggregation function with Partition by clause
This helps you to check if there is a lower than 50 mark for that student, if so it makes all records for that student as REPEATER status
;with cte as (
select
*,
term_1 + term_2 as total
from tbl_Marks
)
select
*,
case when (term_1 + term_2) >= 50 then 'PASS' else 'FAIL' end as status,
case when (
min(total) over (partition by Std_id)
) >= 50 then 'PROMOTED' else 'REPEATER' end as PROMOTION_status
from cte
I hope it helps,
Related
I would like to subtract each row "Value" with the "Value" where Sub1=0 grouping by ID_1 and ID_2 using a SQL query.
This is the table structure:
------------------------------------
ID_1 |ID_2 | sub1 | Value
------------------------------------
1 | a | 0 | 20
1 | a | 50 | 30
1 | a | 100 | 40
1 | b | 0 | 25
1 | b | 50 | 30
1 | b | 100 | 50
2 | a | 0 | 5
2 | a | 50 | 10
2 | a | 100 | 30
2 | b | 0 | 25
2 | b | 50 | 50
2 | b | 100 | 70
I would like to group by ID_1 and ID_2 and subtract each row's value with the value where the Sub1=0
Output table should be :
------------------------------------
ID_1 |ID_2 | sub1 | Value | Diff
------------------------------------
1 | a | 0 | 20 | 0
1 | a | 50 | 30 | 10
1 | a | 100 | 40 | 20
1 | b | 0 | 25 | 0
1 | b | 50 | 30 | 5
1 | b | 100 | 50 | 25
2 | a | 0 | 5 | 0
2 | a | 50 | 10 | 5
2 | a | 100 | 30 | 25
2 | b | 0 | 25 | 0
2 | b | 50 | 50 | 25
2 | b | 100 | 70 | 45
Use a window function:
select t.*,
(value -
sum(case when sub1 = 0 then value else 0 end) over (partition by id_1, id_2)
) as diff
from t;
This should work:
select t1.*, t1.value - t2.value as diff
from t t1
left join t t2 on t2.id_1 = t1.id_1 and t2.id_2 = t1.id_2 and t2.sub1 = 0
See it here:
http://sqlfiddle.com/#!9/cab4d5/1
So, I have to calculate total Type A where From & To in between From & To Type B based on ID.
I can't describe it in good words, so this is the example and my expected result (Column Count) :
ID | Type | From | To | Count
-------------------------------
100 | A | 10 | 14 |
100 | A | 16 | 18 |
100 | B | 12 | 14 | 1
100 | B | 11 | 13 | 1
100 | B | 17 | 18 | 1
120 | A | 5 | 10 |
120 | A | 12 | 14 |
120 | A | 18 | 20 |
120 | A | 18 | 20 |
120 | A | 22 | 24 |
120 | B | 30 | 32 | 0
120 | B | 19 | 20 | 2
120 | B | 10 | 14 | 1
Anybody can help ? I'm expecting something similar like COUNT OVER or RANK OVER without GROUP BY because the table above is not original table, its from another subquery..
Hmmmm . . . I think a correlated subquery does what you want:
select t.*,
(case when type = 'B'
then (select count(*)
from t t2
where t2.type = 'A' and
t2.from >= t.to and
t2.to <= t.from
)
end) as count
from t;
I'm not sure if the logic for between includes the endpoints. Traditionally, in SQL, it does. But if that is not your intention, then you may need < or >.
I have a tabel that looks like this:
|--------+------+---------|------|
| Head | ID | Amount | Rank |
|--------+------+---------|------|
| 1 | 10 | 1000 | 1 |
| 1 | 11 | 1200 | 2 |
| 1 | 12 | 1500 | 3 |
| 2 | 20 | 3400 | 1 |
| 2 | 21 | 3600 | 2 |
| 2 | 22 | 4200 | 3 |
| 2 | 23 | 1700 | 4 |
|--------+------+---------|------|
I want a new column (New_column) that does the following:
|--------+------+---------|------|------------|
| Head | ID | Amount | Rank | New_column |
|--------+------+---------|------|------------|
| 1 | 10 | 1000 | 1 | 1000 |
| 1 | 11 | 1200 | 2 | 1000 |
| 1 | 12 | 1500 | 3 | 1200 |
| 2 | 20 | 3400 | 1 | 3400 |
| 2 | 21 | 3600 | 2 | 3400 |
| 2 | 22 | 4200 | 3 | 3600 |
| 2 | 23 | 1700 | 4 | 4200 |
|--------+------+---------|------|------------|
Within each Head number, if rank is not 1, takes the amount of row within the Head number with Rank number before it (Rank 2 takes the amount of Rank 1 within the same Head and Rank 3 takes the amount of Rank 2 within the same Head and so on...)
I know how to fix it with a For loop in other programming languages but Don't know how to do it with SQL.
I think you basically want lag():
select t.*,
lag(amount, 1, amount) over (partition by head order by rank) as new_column
from t;
The three-argument form of lag() allows you to provide a default value.
You can join the same table(subquery) on rank-1 of derived table.
select t1.*,case when t1.rank=1 then amount else t2.amount new_amount
from your_table t1 left join (select Head,ID,Amount,Rank from your_table) t2
on t1.head=t2.head and t1.rank=t2.rank-1
You can use this update:
UPDATE your_table b
SET New_column = CASE WHEN rank = 1 then Amount
ELSE (select a.Amount FROM your_table a where a.ID = b.ID and a.rank = b.rank-1) END
I am a newbie to OrientDB. I have a table structure as shown below. I have tried out a lot of queries but still cannot figure out how to implement the following SQL query in OrientDB. I need to join data from 4 different classes. Any help is greatly appreciated.
select Users.Name as uName,
Shops.Name as shopName,
ShopTotalPurchases.Total
from Users, Shops, Purchases,ShopTotalPurchases
where Users.Id=10
and Purchases.UserId=Users.Id
and Purchases.Date="date2"
and ShopTotalPurchases.Date="date2"
and ShopTotalPurchases.ShopId = Shops.Id
> reldb> SELECT * FROM Users;
+----+--------+-------+
| Id | Name | Phone |
+----+----------------+
| 10 | User 1 | 1111 |
+----+----------------+
| 20 | User 2 | 2222 |
+----+----------------+
> reldb> SELECT * FROM Shops;
+----+--------+-------+
| Id | Name | Phone |
+----+----------------+
| 30 | Shop 1 | 1111 |
+----+----------------+
| 40 | Shop 2 | 2222 |
+----+----------------+
> reldb> SELECT * FROM Purchases; [unique per combo of UserId, ShopId and Date]
+----+--------+--------+--------+------+-----------+
| Id | UserId | Item | ShopId | Date | ItemPrice |
+----+--------+-----------------+------+-----------+
| 0 | 10 | First | 30 |date1 | 100 |
+----+--------+--------+--------+------+-----------+
| 1 | 10 | Second | 30 |date2 | 200 |
+----+--------+--------+--------+------+-----------+
| 21 | 10 | Third | 40 |date3 | 300 |
+----+--------+--------+--------+------+-----------+
| 41 | 20 | Fourth | 40 |date4 | 400 |
+----+--------+--------+--------+------+-----------+
| 82 | 20 | Fift | 30 |date5 | 500 |
+----+--------+--------+--------+------+-----------+
> reldb> SELECT * FROM ShopTotalPurchases;
+----+--------+--------+------+
| Id | Total | ShopId | Date |
+----+--------+--------+------+
| 0 | 1000 | 30 |date1 |
+----+--------+--------+------+
| 1 | 2000 | 30 |date2 |
+----+--------+--------+------+
| 21 | 3000 | 40 |date2 |
+----+--------+--------+------+
you can use this query:
select $a.Name as uName, $b.Name as shopName, $c.Total as Total from Purchases
let $a = (select Name from User where Id = 10 and Id in $parent.current.UserId),
$b = (select Name from Shops where Id in $parent.current.ShopId),
$c = (select Total from ShopTotalPurchases where Date = 'date2' and ShopId in $parent.current.ShopId)
where Date = 'date2' unwind uName, shopName, Total
Console output:
----+------+-----+--------+------
# |#CLASS|uName|shopName|Total
----+------+-----+--------+------
0 |null |User1|Shop1 |2000.0
----+------+-----+--------+------
I'm using SQL Server 2008 R2. I have a table called tstResult in my database.
AI SubID StudID StudName TotalMarks ObtainedMarks
--------------------------------------------------------
1 | 1 | 1 | Jakir | 100 | 90
2 | 1 | 2 | Rubel | 100 | 75
3 | 1 | 3 | Ruhul | 100 | 82
4 | 1 | 4 | Beauty | 100 | 82
5 | 1 | 5 | Bulbul | 100 | 96
6 | 1 | 6 | Ripon | 100 | 82
7 | 1 | 7 | Aador | 100 | 76
8 | 1 | 8 | Jibon | 100 | 80
9 | 1 | 9 | Rahaat | 100 | 82
Now I want a SELECT query that generate a merit list according to the Obtained Marks. In this query obtained marks "96" will be the top in the merit list and all the "82" marks will be placed one after another in the merit list. Something like this:
StudID StudName TotalMarks ObtainedMarks Merit List
----------------------------------------------------------
| 5 | Bulbul | 100 | 96 | 1
| 1 | Jakir | 100 | 90 | 2
| 9 | Rahaat | 100 | 82 | 3
| 3 | Ruhul | 100 | 82 | 3
| 4 | Beauty | 100 | 82 | 3
| 6 | Ripon | 100 | 82 | 3
| 8 | Jibon | 100 | 80 | 4
| 7 | Aador | 100 | 76 | 5
| 2 | Rubel | 100 | 75 | 6
;with cte as
(
select *, dense_rank() over (order by ObtainedMarks desc) as Merit_List
from tstResult
)
select * from cte order by Merit_List desc
you need to use Dense_rank()
select columns from tstResult order by ObtainedMarks desc