I have the following table in SQL Server:
KEY_ID
DEMAND
DAY
STOCKS
SORT
10
5.263
5
3
0
10
5.263
6
0
1
10
5.263
7
0
2
10
5.263
8
0
3
10
5.263
9
0
4
10
5.263
10
0
5
10
5.263
11
2
6
10
5.263
12
0
7
10
5.263
13
0
8
10
5.263
14
0
9
10
5.263
15
0
10
10
5.263
16
0
11
10
5.263
17
0
12
10
5.263
18
0
13
10
5.263
19
1
14
10
5.263
1
0
20
10
5.263
2
0
21
10
5.263
3
0
22
10
5.263
4
0
23
I'd like to partition the table every time there is a change in the STOCKS column. For example, the first partition would include days 5, 6, 7, 8, 9, and 10. The second partition would include 11, 12, 13, 14, 15, 16, 17, and 18 etc. The goal is to sum the demand column for each partition, but I can't figure out how to write the PARTITION BY clause to recognize the various "buckets".
You can do it using window funtion SUM() OVER() to mark the group of days based on STOCKS column
with cte as (
SELECT *, SUM(STOCKS) OVER(ORDER BY SORT) AS cumulative_STOCKS
FROM mytable t
)
select MAX(STOCKS) AS STOCKS, SUM(DEMAND) AS SUM_DEMAND
from cte
GROUP BY cumulative_STOCKS
Demo here
Related
I have query problem, I'm using Google BigQuery (Just to give you context if it is different). I need two value which is Value_A and Value_B. Value_A is top X value, and Value_B is the rest of top X value.Here's my Input Table
Date Value
20 10
19 10
18 10
17 10
16 10
15 10
14 10
13 10
12 10
11 10
10 10
9 10
8 10
7 10
6 10
5 10
4 10
3 10
2 10
1 10
In this case, the value of X is 6, but I need to be configurable.
In date 20, Value_A is sum from the 6 top data in Value (which is date 14 to 20), and Value_B is sum of rest of top data (which is date 14 an below).
In date 19, Value_A is sum from the 6 top data in Value (which is date 13 to 19), and Value_B is sum of rest of top data (which is date 13 an below).
Here's my output
Date Value Value_A Value_B
20 10 60 140
19 10 60 130
18 10 60 120
17 10 60 110
16 10 60 100
15 10 60 90
14 10 60 80
13 10 60 70
12 10 60 60
11 10 60 50
10 10 60 40
9 10 60 30
8 10 60 20
7 10 60 10
6 10 60 0
5 10 50 0
4 10 40 0
3 10 30 0
2 10 20 0
1 10 10 0
Below is for BigQuery Standard SQL
#standardSQL
SELECT date, value,
SUM(value) OVER(ORDER BY date DESC ROWS BETWEEN CURRENT ROW AND 5 FOLLOWING) Value_A,
IFNULL(SUM(value) OVER(ORDER BY date DESC ROWS BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING), 0) Value_B
FROM `project.dataset.table`
-- ORDER BY date DESC
If to apply to sample data from your question, as in below example
#standardSQL
WITH `project.dataset.table` AS (
SELECT 20 date, 10 value UNION ALL
SELECT 19, 10 UNION ALL
SELECT 18, 10 UNION ALL
SELECT 17, 10 UNION ALL
SELECT 16, 10 UNION ALL
SELECT 15, 10 UNION ALL
SELECT 14, 10 UNION ALL
SELECT 13, 10 UNION ALL
SELECT 12, 10 UNION ALL
SELECT 11, 10 UNION ALL
SELECT 10, 10 UNION ALL
SELECT 9, 10 UNION ALL
SELECT 8, 10 UNION ALL
SELECT 7, 10 UNION ALL
SELECT 6, 10 UNION ALL
SELECT 5, 10 UNION ALL
SELECT 4, 10 UNION ALL
SELECT 3, 10 UNION ALL
SELECT 2, 10 UNION ALL
SELECT 1, 10
)
SELECT date, value,
SUM(value) OVER(ORDER BY date DESC ROWS BETWEEN CURRENT ROW AND 5 FOLLOWING) Value_A,
IFNULL(SUM(value) OVER(ORDER BY date DESC ROWS BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING), 0) Value_B
FROM `project.dataset.table`
ORDER BY date DESC
result is
Row date value Value_A Value_B
1 20 10 60 140
2 19 10 60 130
3 18 10 60 120
4 17 10 60 110
5 16 10 60 100
6 15 10 60 90
7 14 10 60 80
8 13 10 60 70
9 12 10 60 60
10 11 10 60 50
11 10 10 60 40
12 9 10 60 30
13 8 10 60 20
14 7 10 60 10
15 6 10 60 0
16 5 10 50 0
17 4 10 40 0
18 3 10 30 0
19 2 10 20 0
20 1 10 10 0
I have a query where I would like to manipulate a column to return an array conatining only the max-value from the last 12 values from another column (due to other parts of the query).
Example:
I want to add the column MaxLast12 from:
Month Power
1 10
2 16
3 8
4 14
5 15
6 3
7 6
8 10
9 11
10 12
11 12
12 12
13 18
14 12
To become:
Month Power MaxLast12
1 10 10
2 16 16
3 8 16
4 14 16
5 15 16
6 3 16
7 6 16
8 17 17
9 11 17
10 12 17
11 12 17
12 12 17
13 18 18
14 12 18
It would also help to be able to create a simpler solution where I only include the 12 rows in the query (won't be as accurate but good enough for the purpose) with only the maximum value. Would need to do the following:
Month Power
1 6
2 6
3 8
4 14
5 15
6 3
7 6
8 10
9 11
10 12
11 12
12 12
To become:
Month Power YearMax
1 10 17
2 16 17
3 8 17
4 14 17
5 15 17
6 3 17
7 6 17
8 17 17
9 11 17
10 12 17
11 12 17
12 12 17
Since I'm guessing both problems solution will be similar, any help possible is appriciated. Would like to avoid usign GROUP BY clause since I'm modifying an existing kind of complex query.
Tried to achive this using max() with no luck.
I am using SQL-developer.
In Oracle you would use window functions:
select month, power,
max(power) over (order by month rows between 11 preceding and current row)
from t;
My original table looks like:
id, date, 1, 2, 3,
1 1 10 10 10
1 2 20 20 20
1 3 30 30 30
1 4 15 15 15
By running the query:
ARRAY_AGG(STRUCT(1, 2, 3)) OVER (PARTITION BY id ORDER BY date ROWS BETWEEN 2
PRECEDING AND CURRENT ROW)
I get this output
1 2 3
1 10 10 10
2 10 10 10
20 20 20
3 10 10 10
20 20 20
30 30 30
4 20 20 20
30 30 30
15 15 15
I would like the output to be:
1 2 3
1 10 10 10
2 20 20 20
10 10 10
3 30 30 30
20 20 20
10 10 10
4 15 15 15
30 30 30
20 20 20
So bascically, the values that I get in my output are all correct, but I would like order of the output to be flipped. Anyone know how to do that with an array(struct)) type of column?
One option is to reverse the sort order of the window clause, or you could use a simple solution of calling the ARRAY_REVERSE function:
ARRAY_REVERSE(
ARRAY_AGG(STRUCT(col1, col2, col3)) OVER (
PARTITION BY id ORDER BY date
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
)
Added below for the sake of having reverse the sort order of the window clause option here
ARRAY_AGG(STRUCT(col1, col2, col3)) OVER(
PARTITION BY id ORDER BY date DESC
ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
Thanks in advance for any assistance you can provide. I have spent hours on this with no luck.
I'm working with an indented bill of material table which has an end part id, a sequence number, a level and a quantity. The goal is to determine the total cumulative quantity of each row on this table.
What makes this difficult is that to determine the total quantity, the child quantity needs to be multiplied by it's parent quantity. The parent quantity of that parent needs to be multiplied by it's parent quantity and so on.
For example, a level 3 part has a component quantity of 5. It's parent the level 2 part has a component quantity of 2. It's parent the level 1 part has a component quantity of 3. This means the level 3 part total quantity is 30 (3 X 2 X 5).
With the assistance of SO (specifically #KKK) the parent quantity was able to be calculated in the below query. After this was resolved I realized I now need two additional columns, one that shows the Rolled/Cumulative quantities of the parent rows and one that shows the total quantity of the child.
The attached screenshot has the two columns that need to be added highlighted in yellow. Here is the current SQL (using Oracle 10.2) for the columns that are not in yellow:
select
end_part_id, sort_seq_no, indented_lvl, comp_qty,
(select distinct first_value(a.comp_qty) over (order by a.sort_seq_no desc, TRIM(a.indented_lvl) desc)
from
report_table a
where
a.end_part_id = b.end_part_id
and a.sort_seq_no < b.sort_seq_no
and TRIM(a.indented_lvl) < TRIM(b.indented_lvl)) as "PARENT_QTY"
from report_table b
Expected Results
END_PART_ID SORT_SEQ_NO INDENTED_LVL COMP_QTY PARENT_QTY ROLLED_PARENT QTY TOTAL_QTY
PARTX 1 1 2 1 1 2
PARTX 2 2 5 2 2 10
PARTX 3 3 2 5 10 20
PARTX 4 4 1 2 20 20
PARTX 5 5 1 1 20 20
PARTX 6 6 1 1 20 20
PARTX 7 5 4 1 20 80
PARTX 8 6 1 4 80 80
PARTX 9 2 7 2 2 14
PARTX 10 3 2 7 14 28
PARTX 11 3 2 7 14 28
PARTX 12 4 1 2 28 28
PARTX 13 4 1 2 28 28
PARTX 14 3 8 7 14 112
PARTX 15 1 1 1 1 1
PARTX 16 2 7 1 1 7
PARTX 17 3 2 7 7 14
PARTX 18 3 2 7 7 14
PARTX 19 4 1 2 14 14
PARTX 20 4 1 2 14 14
I have a table named team and it like below: I just added a row_number in the 3rd column
RaidNo OutComeID RN
2 15 1
4 15 2
6 14 3
8 16 4
10 16 5
12 14 6
14 16 7
16 15 8
18 15 9
20 16 10
22 12 11
24 16 12
26 16 13
28 16 14
30 15 15
32 14 16
34 13 17
When the OutcomeId came as 16 then start with one and 16 comes consecutively, add one by one. And the results be like
RaidNo OutComeID RN Result
2 15 1 0
4 15 2 0
6 14 3 0
8 16 4 1
10 16 5 2
12 14 6 0
14 16 7 1
16 15 8 0
18 15 9 0
20 16 10 1
22 12 11 0
24 16 12 1
26 16 13 2
28 16 14 3
30 15 15 0
32 14 16 0
34 13 17 0
Help me to get the result.
You can use the following query:
SELECT RaidNo, OutComeID, RN,
CASE
WHEN OutComeID <> 16 THEN 0
ELSE ROW_NUMBER() OVER (PARTITION BY OutComeID, grp ORDER BY RN)
END AS Result
FROM (
SELECT RaidNo, OutComeID, RN,
RN - ROW_NUMBER() OVER (PARTITION BY OutComeID ORDER BY RN) AS grp
FROM mytable) AS t
ORDER BY RN
Field grp identifies slices (also called islands) of consecutive records having the same OutComeID value. The outer query uses grp in order to enumerate each record that belongs to a '16' slice. The records that belong to the other slices are assigned value 0.
Demo here