I am using Big query to extract results from employee learning table. I need to figure out if an employee has completed a set of courses for a department. For example if an employee complete all of these three courses say, course 100, course 200 and course 300, they can be classified as as compliant else They are non-compliant. I have created a dummy example of how my data is structured, unfortunately due to organization policy I cant share more information.
Problem statement.
Say employee who has completed course 100,200,300 They are compliant in Bakery else they are non-complaint. Employee must complete all three courses to be compliant.
Employee who has completed course 100 and 300 They are compliant in Fruit & Veg else they are non-complaint. They must complete above mention two courses to be compliant.
Employee who has completed course 75,85,95 They are compliant in Grocery else non-compliant. Same here they must have done three courses so that they can be compliant.
Employee who has completed 101 and 102 They are compliant in Nighfill else non-compliant.
Please note employee must complete all the sets to be compliant in relevant categories
Employee course
1 100
1 101
1 200
1 300
1 300
1 400
2 100
2 200
3 100
3 200
3 300
4 75
4 85
4 95
4 105
4 115
4 125
5 200
5 200
5 100
5 100
5 100
5 300
5 300
6 100
7 100
8 300
8 200
8 100
8 101
8 102
9 100
9 200
9 300
Structure of Data
I am still thinking about the solution.
Consider below approach
select Employee,
ifnull(array_length(split(string_agg(distinct if(course in (100,200,300), '' || course, null)))), 0) = 3 isBakeyCompliant,
ifnull(array_length(split(string_agg(distinct if(course in (100,300) and not course in (200), '' || course, null)))), 0) = 2 isFruitVegCompliant,
ifnull(array_length(split(string_agg(distinct if(course in (75,85,95), '' || course, null)))), 0) = 3 isGroceryCompliant,
ifnull(array_length(split(string_agg(distinct if(course in (101,102), '' || course, null)))), 0) = 3 isNighfillCompliant,
from your_table
group by Employee
with output
Related
Imagine we have user balances. There's a table with top-up and withdrawals. Let's call it balance_updates.
transaction_id
user_id
current_balance
amount
created_at
1
1
100
100
...
2
1
0
-100
3
2
400
400
4
2
300
-100
5
2
200
-200
6
2
300
100
7
2
50
-50
What I want to get off this is a list of top-ups and their leftovers using the first in first out technique for each user.
So the result could be this
top_up
user_id
leftover
1
1
0
3
2
50
6
2
100
Honestly, I struggle to turn it to SQL. Tho I know how to do it on paper. Got any ideas?
Consider the following table, describing a patients medication plan. For example, the first row describes that the patient with patient_id = 1 is treated from timestamp 0 to 4. At time = 0, the patient has not yet become any medication (kum_amount_start = 0). At time = 4, the patient has received a kumulated amount of 100 units of a certain drug. It can be assumed, that the drug is given in with a constant rate. Regarding the first row, this means that the drug is given with a rate of 25 units/h.
patient_id
starttime [h]
endtime [h]
kum_amount_start
kum_amount_end
1
0
4
0
100
1
4
5
100
300
1
5
15
300
550
1
15
18
550
700
2
0
3
0
150
2
3
6
150
350
2
6
10
350
700
2
10
15
700
1100
2
15
19
1100
1500
I want to add the two columns "kum_amount_start_last_6hr" and "kum_amount_end_last_6hr" that describe the amount that has been given within the last 6 hours of the treatment (for the respective timestamps start, end).
I'm stuck with this problem for a while now.
I tried to tackle it with something like this
SUM(kum_amount) OVER (PARTITION BY patient_id ROWS BETWEEN "dynmaic window size" AND CURRENT ROW)
but I'm not sure whether this is the right approach.
I would be very happy if you could help me out here, thanks!
I am trying to change something like this:
Index Record Time
1 10 100
1 10 200
1 10 300
1 10 400
1 3 500
1 10 600
1 10 700
2 10 800
2 10 900
2 10 1000
3 5 1100
3 5 1200
3 5 1300
into this:
Index CountSeq Record LastTime
1 4 10 400
1 1 3 500
1 2 10 700
2 3 10 1000
3 3 5 1300
I am trying to apply this logic per unique index -- I just included three indexes to show the outcome.
So for a given index I want to combine them by streaks of the same Record. So notice that the first four entries for Index 1 have Records 10, but it is more succinct to say that there were 4 entries with record 10, ending at time 400. Then I repeat the process going forward, in sequence.
In short I am trying to perform a count-grouping over sequential chunks of the same Record, within each index. In other words I am NOT looking for this:
select index, count(*) as countseq, record, max(time) as lasttime
from Table1
group by index,record
Which combines everything by the same record whereas I want them to be separated by sequence breaks.
Is there a way to do this in SQL?
It's hard to solve your problem without having a single primary key, so I'll assume you have a primary key column that increases each row (primkey). This request would return the same table with a 'diff' column that has value 1 if the previous primkey row has the same index and record as the current one, 0 otherwise :
SELECT *,
IF((SELECT index, record FROM yourTable p2 WHERE p1.primkey = p2.primkey)
= (SELECT index, record FROM yourTable p2 WHERE p1.primkey-1 = p2.primkey), 1, 0) as diff
FROM yourTable p1
If you use a temporary variable that increases each time the IF expression is false, you would get a result like this :
primkey Index Record Time diff
1 1 10 100 1
2 1 10 200 1
3 1 10 300 1
4 1 10 400 1
5 1 3 500 2
6 1 10 600 3
7 1 10 700 3
8 2 10 800 4
9 2 10 900 4
10 2 10 1000 4
11 3 5 1100 5
12 3 5 1200 5
13 3 5 1300 5
Which would solve your problem, you would just add 'diff' to the group by clause.
Unfortunately I can't test it on sqlite, but you should be able to use variables like this.
It's probably a dirty workaround but I couldn't find any better way, hope it helps.
I need one adaptation for the first table because there are negative issues points and I need the net table considerating the negatives points as debit of the first time of issue. E.g:
Date of issue Number of account Issued points
30-abr 1 300
31-may 1 50
30-jun 1 100
30-jun 1 -50
30-abr 2 200
31-may 2 60
I want this table
Date of issue Number of account Issued points
30-abr 1 250
31-may 1 50
30-jun 1 100
30-abr 2 200
31-may 2 60
I have a table which says that All students have to take 10 courses, in which 5 are mandatory and choose 3 from other 5. So basically has 2 groups. Now I need to calculate the sum of total Credits and also Sum of group Credits.
Table #1
StudentID ProgID ProgName GroupID GroupName Course Complete_Courses_Alert Credits
1 100 MS 501 Mandatory 12 Remaining 3
1 100 MS 501 Mandatory 13 Complete 3
1 100 MS 501 Mandatory 14 Complete 3
1 100 MS 501 Mandatory 15 Remaining 3
1 100 MS 501 Mandatory 16 Complete 3
1 100 MS 502 Elective 17 Complete 3
1 100 MS 502 Elective 18 Complete 3
1 100 MS 502 Elective 19 Remaining 3
1 100 MS 502 Elective 20 Complete 3
1 100 MS 502 Elective 21 Remaining 3
I want the output as
the above table but with 2 fields more added to it.
i.e. Sum of Completed Credits(Total Credits)
and Sum Complete Credits(By Group)
This is what I have done so far,
I have created a view for calculating total credits and GrouptotalCredits and then joinin it on the main query. This way again i need to create another view to execute more functions on the query..
Can anyone help.
I think you're looking for something like:
select *
, StudentGroupCredits = sum(case when Complete_Courses_Alert = 'Complete' then Credits else 0 end) over (partition by StudentId, GroupName)
, StudentTotalCredits = sum(case when Complete_Courses_Alert = 'Complete' then Credits else 0 end) over (partition by StudentId)
from Courses
SQL Fiddle with demo.
Check out OVER Clause at Books Online for more information.