I have TABLE1 and TABLE2 as below:
TABLE1
STUDENT
DAY
SCORE
1
7
0
1
9
10
2
3
10
2
5
3
3
9
10
TABLE2
STUDENT
DAY
TEST
1
7
1
1
8
2
1
9
7
2
5
5
3
8
9
4
4
10
I need a query to JOIN TABLE2 to TABLE1 and then create column SCOREVSTEST which goes like this:
if SCORE >= TEST then SCOREVSTEST = 'SCORE >= TEST'
if SCORE < TEST then SCOREVSTEST = 'SCORE < TEST'
This my desirable output
STUDENT
DAY
SCORE
TEST
SCOREVSTEST
1
7
0
1
SCORE < TEST
1
9
10
7
SCORE >= TEST
2
5
3
5
SCORE < TEST
This is what I have so far:
SELECT *
FROM TABLE1
LEFT JOIN TABLE2
ON TABLE1.STUDENT = TABLE2.STUDENT
AND TABLE1.DAY = TABLE2.DAY
CASE WHEN SCORE >= TEST THEN 'SCORE>= TEST'
ELSE 'SCORE<TEST' END AS SCOREVSTEST
You have the right idea, but this case expression should be in the select list, not part of or after the join:
SELECT table1.student, table1.day, score, test,
CASE WHEN score >= test THEN 'SCORE >= TEST' ELSE 'SCORE < TEST' END
AS scorevtest
FROM table1
LEFT JOIN table2 ON ON table1.student = table2.student AND table1.day = table2.day
Related
I have 2 tables like below
id
score1
1
4
2
5
3
6
id
score2
score3
2
7
9
3
8
10
4
7
9
5
8
10
And I want to join them together to achive this result
id
score1
score2
score3
total
1
4
0
0
4
2
5
7
9
21
3
6
8
10
24
4
0
7
9
16
5
0
8
10
18
How ever, i have tried all join type but the id column have null values in them, can you guys show me the solution for this? Thanks all
select
coalesce(t1.id,t2.id) id
, coalesce(t1.score1,0) score1
, coalesce(t2.score2,0) score2
, coalesce(t2.score3,0) score3
, coalesce(t1.score1,0) + coalesce(t2.score2,0) + coalesce(t2.score3,0) total
from table1 t1
full outer join table2 t2
on t1.id = t2.id
db<>fiddle here
SELECT COALESCE(C.ID,C2.ID)ID,COALESCE(C.SCORE1,0)SCORE1,
COALESCE(C2.SCORE2,0)SCORE2,COALESCE(C2.SCORE3,0)SCORE3,
COALESCE(C.SCORE1,0)+COALESCE(C2.SCORE2,0)+COALESCE(C2.SCORE3,0) TOTAL
FROM CTE AS C
FULL JOIN CTE2 C2 ON C.ID=C2.ID
ORDER BY ID
CTE - is yours first table(id,score1),CTE2 - second table(id,score2,score3)
You need to join in the ID.
Something like this (not tested) :
SELECT
t1.id,
ISNULL(t1.score1, 0)
ISNULL(t2.score2, 0)
ISNULL(t2.score3, 0)
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
LEFT JOIN instead of inner join or else you would only get lignes existing in t1
I have a data (dt) in SQL like the following:
ID time_id act rd
11 1 1 1
11 2 4 1
11 3 7 0
12 1 8 1
12 2 2 0
12 3 4 1
12 4 3 1
12 5 4 1
13 1 4 1
13 2 1 0
15 1 3 1
16 1 8 0
16 2 8 0
16 3 8 0
16 4 8 0
16 5 8 0
and I want to take the subset of this data such that only ids (and their corresponding time_id, act, rd) that has time_id == 5 is retained. The desired output is the following
ID time_id act rd
12 1 8 1
12 2 2 0
12 3 4 1
12 4 3 1
12 5 4 1
16 1 8 0
16 2 8 0
16 3 8 0
16 4 8 0
16 5 8 0
I know I should use having clause somehow but have not been successful so far (returns me empty outputs). below is my attempt:
SELECT * FROM dt
GROUP BY ID
Having min(time_id) == 5;
This query:
select id from tablename where time_id = 5
returns all the ids that you want in the results.
Use it with the operator IN:
select *
from tablename
where id in (select id from tablename where time_id = 5)
You can use a correlated subquery with exists:
select t.*
from t
where exists (select 1 from t t2 where t2.id = t.id and t2.time_id = 5);
WITH temp AS
(
SELECT id FROM tab WHERE time_id = 5
)
SELECT * FROM tab t join temp tp on(t.id=tp.id);
check this query
select * from table t1 join (select distinct ID from table t where time_id = 5) t2 on t1.id =t2.id;
In example I want to subtract the Subtracted value in TABLE 1 from the Sum Total of the ValueBefore in Table 2 grouped by the GroupID. Value subtracted from first row and if remainder then that is subtracted off the following row in group (and so on) until total is subtracted.
Is there a way to do this without iterating through rows to get the remainder?
My table 1:
TABLE 1 of subtracting value
GroupID Subtracted
1 32
2 30
My table 2:
ID GroupID ValueBefore Reduction ValueAfter
1 1 10 -10 0
2 1 15 -15 0
3 1 5 -5 0
4 1 5 -2 3
5 2 40 -30 10
6 2 30 0 30
I would use a cumulative sum and some relatively simple comparisons:
select t2.*,
(case when t2.running_value - t2.valuebefore < t1.subtracted
then 0
when t2.running_value < t1.subtracted
then t2.running_value - t1.subtracted
else t2.valuebefore
end) as reduction,
(case when t2.running_value < t1.subtracted then 0
else t2.running_value - t1.subtracted
end) as ValueAfter
from (select t2.*,
sum(valuebefore) over (partition by groupid order by id) as running_value
from t2
) t2 join
t1
on t2.groupid = t1.groupid;
One method is to use a LEFT JOIN in order to calculate the running total of ValueBefore.
This query:
SELECT t2.ID, t2.GroupID, t2.ValueBefore, r.ValueBefore AS rValueBefore
FROM Table2 AS t2
LEFT JOIN Table2 AS r
ON t2.GroupID = r.GroupID AND t2.ID >= r.ID
ORDER BY t2.ID, r.ID
produces this output:
ID GroupID ValueBefore rValueBefore
------------------------------------
1 1 10 10
2 1 15 10
2 1 15 15
3 1 5 10
3 1 5 15
3 1 5 5
4 1 5 10
4 1 5 15
4 1 5 5
4 1 5 5
5 2 40 40
6 2 30 40
6 2 30 30
You can now calculate the running total if you group by ID and SUM on rValueBefore:
SELECT t2.ID, t2.GroupID, t2.ValueBefore, SUM(r.ValueBefore) AS Total
FROM Table2 AS t2
LEFT JOIN Table2 AS r
ON t2.GroupID = r.GroupID AND t2.ID >= r.ID
GROUP BY t2.ID, t2.GroupID, t2.ValueBefore
Output:
ID GroupID ValueBefore Total
-----------------------------
1 1 10 10
2 1 15 25
3 1 5 30
4 1 5 35
5 2 40 40
6 2 30 70
You can now calculate ValueAfter using:
SELECT t.ID, t.GroupID, t.ValueBefore, Total,
Subtracted,
CASE
WHEN Total - t1.Subtracted < 0 THEN 0
ELSE Total - t1.Subtracted
END AS ValueAfter
FROM
(
SELECT t2.ID, t2.GroupID, t2.ValueBefore, SUM(r.ValueBefore) AS Total
FROM Table2 AS t2
LEFT JOIN Table2 AS r
ON t2.GroupID = r.GroupID AND t2.ID >= r.ID
GROUP BY t2.ID, t2.GroupID, t2.ValueBefore
) as t
JOIN Table1 AS t1 ON t.GroupID = t1.GroupID
ORDER BY ID
Output:
ID GroupID ValueBefore Total Subtracted ValueAfter
-------------------------------------------------------
1 1 10 10 32 0
2 1 15 25 32 0
3 1 5 30 32 0
4 1 5 35 32 3
5 2 40 40 30 10
6 2 30 70 30 40
Demo here
I need to get the sum of all TOTAL fields where the ID, RECNO and DRCR fields have the same value, while also displaying these fields in the result set.
eg
ID RECNO SECRECNO DRCR TOTAL
1 9 5 D 25
1 9 12 D 22
1 9 6 C 33
1 9 5 D 50
1 8 2 D 12
1 8 2 C 23
2 9 5 D 100
So the results of the query should be
ID RECNO SECRECNO DRCR SUM(TOTAL)
1 9 5 D 75
1 9 12 D 22
1 9 6 C 33
1 8 2 D 12
1 8 2 C 23
2 9 5 D 100
This query will give the results set, without the TOTAL:
select distinct t1.recno, t1.secrecno
from table t1, table t2
where t1.recno = t2.recno and t.id = '1' and t1.drcr = 'D'
But I can't see how to SUM the TOTAL of these results.
How to do this?
select t1.id,
t1.recno,
t1.secrecno,
t1.drcr,
SUM( TOTAL )
from table t1
INNER JOIN
table t2
ON ( t1.recno = t2.recno )
WHERE t1.id = '1'
AND t1.drcr = 'D'
GROUP BY
t1.id,
t1.recno,
t1.secrecno,
t1.drcr
I have a requirement to retrieve the data in the below fashion
Weeks delay_count
0 6
1 0
2 3
3 4
4 0
5 1
6 0
7 0
8 0
9 0
10 2
11 0
12 0
13 0
14 0
15 3
Here weeks is the hard coded column from 0 to 15 and delay_count is the derived column. I have a column delay_weeks. Based on the values in this column I need to populate the values in the delay_count column (derived column)
delay_weeks column values are below.
blank
blank
blank
2
10
5
blank
3
2
10
2
3
3
3
0
0
15
22
29
Conditions:
When delay_weeks is blank or 0 then count in the delay_count column should be 1
When delay_weeks is 3 then in the delay_count column the count should be 1 under week 3
When delay_weeks is 10 then in the delay_count column the count should be 1 under week 10
When delay_weeks is greater than or equal to 15 then in the delay_count column the count should be 1 under week 15.
I wrote code like below
SELECT "Weeks", a."delay_count"
FROM (SELECT LEVEL AS "Weeks"
FROM DUAL
CONNECT BY LEVEL <= 15) m,
(SELECT VALUE, COUNT (VALUE) AS "delay_numbers"
FROM (SELECT CASE
WHEN attr11.VALUE >= 15
THEN '15'
ELSE attr11.VALUE
END
VALUE
FROM docs,
(SELECT object_id, VALUE, attribute_type_id
FROM ATTRIBUTES
WHERE attribute_type_id =
(SELECT attribute_type_id
FROM attribute_types
WHERE name_display_code =
'ATTRIBUTE_TYPE.DELAY IN WEEKS')) attr11
WHERE docs.obj_id = attr11.object_id(+)
GROUP BY VALUE) a
WHERE m."Weeks" = a.VALUE(+)
select
weeks,
nvl(cnt, 0) as delay_count
from
(select level-1 as weeks from dual connect by level < 17)
left join (
select
nvl(least(attr11.value, 15), 0) as weeks,
count(0) as cnt
from
DOCS
left join (
ATTRIBUTES attr11
join ATTRIBUTE_TYPES atr_tp using(attribute_type_id)
)
on atr_tp.name_display_code = 'ATTRIBUTE_TYPE.DELAY IN WEEKS'
and docs.obj_id = attr11.object_id
group by nvl(least(attr11.value, 15), 0)
) using(weeks)
order by 1
Reverse-engineering the relevant parts of the table definitions, I think this gives you what you want:
select t.weeks, count(delay) as delay_count
from (select level - 1 as weeks from dual connect by level <= 16) t
left join (
select case when a.value is null then 0
when to_number(a.value) > 15 then 15
else to_number(a.value) end as delay
from docs d
left join (
select a.object_id, a.value
from attributes a
join attribute_types at on at.attribute_type_id = a.attribute_type_id
where at.name_display_code = 'ATTRIBUTE_TYPE.DELAY IN WEEKS'
) a on a.object_id = d.obj_id
) delays on delays.delay = t.weeks
group by t.weeks
order by t.weeks;
With what I think is matching data I get:
WEEKS DELAY_COUNT
---------- -----------
0 6
1 0
2 3
3 4
4 0
5 1
6 0
7 0
8 0
9 0
10 2
11 0
12 0
13 0
14 0
15 3
But obviously since you haven't given the real table structures I'm guessing a bit on the relationships. Obligatory SQL Fiddle.