Firebird 3 SQL windows function over() - sql

I need help..
I have table orders like this
id,order_date,price,customer_id
1 01.01.2001 100 1
2 01.02.2001 0 1
3 20.02.2001 0 1
4 04.04.2001 200 1
I need select result like this
id,order_date,price,customer_id,somefield
1 01.01.2001 100 1 100
2 01.02.2001 0 1 100
3 20.02.2001 0 1 100
3 04.04.2001 200 1 200
Try sql like this
select a.id,order_date,
coalesce(a.price,0) price,
customer_id
sum(coalesce(a.price,0)) OVER (order by a.order_date) somefield,
from tb_orders a
where a.customer_id=4583 and a.orderstate = 1
order by a.order_date
but result gives this
id,order_date,price,customer_id,somefield
1 01.01.2001 100 1 100
2 01.02.2001 0 1 100
3 20.02.2001 0 1 100
3 04.04.2001 200 1 300

You could create subgroup:
SELECT *, MAX(price) OVER(PARTITION BY grp) AS somefield
FROM (
select a.id,order_date,
coalesce(a.price,0) price,
customer_id,
sum(CASE WHEN price = 0 THEN 0 ELSE 1 END) OVER (order by a.order_date) grp
from tb_orders a
where a.customer_id=4583
and a.orderstate = 1
) sub
order by order_date;
db<>fiddle demo

Related

how to sum with case with oracle sql

I m having data in columns as:
item_id
month_in
amount
1
1
1500
1
1
1000
2
1
2500
3
1
2600
3
1
1000
4
1
2700
4
1
1000
1
2
1500
1
2
2000
2
2
1000
3
3
2500
3
3
2500
4
3
1000
4
3
2500
I want to have like this result
item_id
januari
februari
maret
1
2500
3500
0
2
2500
1000
0
3
3600
0
0
4
3700
0
3500
in oracle sql query how to solve this.
please help me
I have try this
select
item_id,
(case month_in=1 then sum(amout) end) AS januari
from table
group by item_id, month_in
order by item_id asc
but not working as I expected
We can try a pivot query here:
SELECT
item_id,
SUM(CASE WHEN month_in = 1 THEN amount ELSE 0 END) AS januari,
SUM(CASE WHEN month_in = 2 THEN amount ELSE 0 END) AS februari,
SUM(CASE WHEN month_in = 3 THEN amount ELSE 0 END) AS maret
FROM yourTable
GROUP BY
item_id
ORDER BY
item_id;
You almost got it. This is the simplest solution, without extra hassle:
SELECT
item_id,
SUM(CASE WHEN month_in = 1 THEN amount ELSE 0 END) AS januari,
SUM(CASE WHEN month_in = 2 THEN amount ELSE 0 END) AS februari,
SUM(CASE WHEN month_in = 3 THEN amount ELSE 0 END) AS maret
from table
group by item_id
order by item_id asc
You don't need to define the months as a separate rowset, because the months are defined as values 1, 2, 3, ... as columns. Similarly, the items are defined by the group by function.

Group by values that are each multiple of number

This is the table t. I want to group it every time the TotalQty >= 5n (let n = group). i.e. once the TotalQty >= 5n I want to sum together the qty from n-1 to n.
ID DateCreated CurrQty
1 01-20-2020 1
2 01-21-2020 4
3 01-22-2020 3
4 01-23-2020 3
5 01-25-2020 1
6 02-13-2020 3
7 02-16-2020 2
With this query I can get pretty close but I doesn't consider the the previous "valid" TotalQty + 5
select DateCreated, CurrQty, TotalQty
, ceiling(TotalQty/5.0) GroupNum
from
(
select DateCreated, CurrQty
, SUM(CurrQty) OVER (ORDER BY DateCreated ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) TotalQty
from t
) t2
ID DateCreated CurrQty TotalQty GroupNum
1 01-20-2020 1 1 1
2 01-21-2020 4 5 1
3 01-22-2020 3 8 2
4 01-23-2020 3 11 3
5 01-25-2020 1 12 3
6 02-13-2020 3 15 3
7 02-16-2020 2 17 4
---
How do I get this result?
ID DateCreated CurrQty TotalQty GroupNum
1 01-20-2020 1 1 1
2 01-21-2020 4 5 1
3 01-22-2020 3 8 2
4 01-23-2020 3 11 2 (from ID2, 11 >= (5+5))
5 01-25-2020 1 12 3
6 02-13-2020 3 15 3
7 02-16-2020 2 17 3 (from ID4, 17 >= (11+5))
And so on, the next group would be until 17+5 = 22
You need to use a recursive CTE for this:
with cte as (
select id, datecreated, currqty, currqty as totalqty, 1 as groupnum
from t
where id = 1
union all
select t.id, t.datecreated, t.currqty,
(case when cte.totalqty >= 5 then t.currqty else t.currqty + cte.totalqty end),
(case when cte.totalqty >= 5 then groupnum + 1 else groupnum end)
from cte join
t
on t.id = cte.id + 1
)
select *
from cte;
EDIT:
Hold on. I think the answer is simpler.
select t.*,
1 + ceil((totalqty - qty + 1) / 5.0)
from (select t.*,
sum(qty) over (order by date) as totalqty
from t
) t;

increasing value with condition on oracle

How to add an increment value (not summarize) with some condition on another column?
I'm using Oracle-like DBMS, named Tibero, for simple example i want to produce this data
ROWNUM GRP_STRT GRP_NO SLBY
1 1 1 1
2 1 1 1
3 1 1 1
4 1 1 1
5 1 1 1
6 1 2 0
7 1 2 0
8 1 3 1
9 1 3 1
10 1 3 1
11 1 4 0
12 1 5 1
Column SLBY is for Buy/Sell code (0=Buy, 1=Sell) then every changing type of transaction, column GRP_NO increasing (but it's not grouping by SLBY column)
SELECT CASE
WHEN ROWNUM = 1 THEN GRP_NO
WHEN ROWNUM <> 1 AND SLBY = LAG(SLBY,1) over (ORDER BY ROWNUM) THEN LAG(GRP_STRT,1) over (ORDER BY ROWNUM) - 1
WHEN ROWNUM <> 1 AND SLBY_DSTN_CD <> LAG(SLBY_DSTN_CD,1) over (ORDER BY ROWNUM) THEN LAG(GRP_STRT,1) over (ORDER BY ROWNUM) + 1
END TARGET_GROUPING
, A.*
FROM SOME_TABLE
I tried with that query but instead of getting what i want like in the picture above, I produced a GRP_NO like 1 1 1 1 1 2 1 1 1 1 2 1 1 1 (first change SLBY only)
Apologies for my bad english and bad explanation, I'll explain more if need further information, thanks for your help!
As far as I understood your problem,
You are trying to calculate GRP_NO from ROWNUM, GRP_STRT, GRP_NO, and SLBY.
I have created the following query for you.
You can check the logic and apply it in your code accordingly:
SELECT
RN,
GRP_STRT,
SUM(CASE
WHEN PREV_SLBY_DSTN_CD IS NULL
OR PREV_SLBY_DSTN_CD <> SLBY_DSTN_CD THEN 1
END) OVER(
ORDER BY
RN
) AS GRP_NO,
SLBY_DSTN_CD AS SLBY
FROM
(
SELECT
RN,
LAG(SLBY_DSTN_CD) OVER(
ORDER BY
RN
) AS PREV_SLBY_DSTN_CD,
SLBY_DSTN_CD,
GRP_STRT
FROM
(SELECT ROWNUM RN, .... FROM SOME_TABLE) A
)
This code is to generate the output as shown in question:
ROWNUM GRP_STRT GRP_NO SLBY
1 1 1 1
2 1 1 1
3 1 1 1
4 1 1 1
5 1 1 1
6 1 2 0
7 1 2 0
8 1 3 1
9 1 3 1
10 1 3 1
11 1 4 0
12 1 5 1
Cheers!!

Need to select 1 row from each group in sql

am trying to do this query. This is what I have.
My table is: Table
QId InternalId type. priority userid
100 100 1 0 X101
100 100 1 1 X102
100 100 2 0 X103
100 100 2 0 X104
100 100 2 0 X105
100 100 3 0 X106
100 100 3 0 X107
101 101 2 1 X114
101 101 2 0 X115
101 101 3 0 X116
101 101 3 0 X117
For QId and InternalId we have type 1,2,3. I need 1 row for each group based type. Here condition is if priority is 1 then we need take that record. if priority is not set need to take first record.
I need result like below table
QId InternalId type. priority userid
100 100 1 1 X102
100 100 2 0 X103
100 100 3 0 x106
101 101 2 1 X114
101 101 3 0 X116
Can you please help me out in this
Just use row_number():
select t.*
from (select t.*,
row_number() over (partition by QId, InternalId, type order by (select null)) as seqnum
from t
) t
where seqnum = 1;
You can try using row_number()
select * from
(
select *, row_number() over(partition by qid, internalid, type order by priority desc) as rn
from tablename
)A where rn=1
use row_number() window function
select t.* from (select *,row_number()over(partition by QId,InternalId,type order by case when priority=1 then 1 else 2 end) rn
) where t.rn=1
Another approach can be WITH TIES like following.
select top 1 with ties *
from #table
order by row_number() over (partition by QId, InternalId, type order by (select 1))
Online Demo

I need 2 count values from single column to be in same row using Over () clause

I have the following Result from Select statement
UnitId UnitType GroupId
1 1 1
2 1 1
3 1 2
4 2 2
5 2 2
6 2 2
7 2 2
I need the following result for each group Id
GroupId CountBasedOnUnitType1 CountBasedOnUnitType2
1 2 0
2 1 4
Thanks in advance.
Try this
SELECT * FROM
(
SELECT GroupId,
UnitType
FROM Table1
) x
Pivot
(
Count(UnitType)
For UnitType in ([1], [2])
) p
Fiddle Demo
Output
GroupId 1 2
1 2 0
2 1 4
Does in necessarily need to have OVER?
select
GroupID,
sum(case when UnitType = 1 then 1 else 0 end) CountBasedOnUnitType1,
sum(case when UnitType = 2 then 1 else 0 end) CountBasedOnUnitType2
from table
group by GroupID