Oracle select from values and substract from last value - oracle

Need help on Oracle SELECT statement.
I Have table like this with used days. User can have 11 days
+----+----------+-----+-----------+
| ID | NAME | USED| DATE |
+----+----------+-----+-----------+
| 1 | John | 1 |01/01/2018 |
| 2 | John | 2 |01/03/2018 |
| 3 | John | 2 |01/05/2018 |
+----+----------+-----+-----------+
So on QUERY SELECT i want to have result of left days like this
+----+----------+------+-----------+
| ID | NAME | DAYS | USED| LEFT|
+----+----------+------+-----------+
| 1 | John | 11 | 1 | 10 |
| 2 | John | 10 | 2 | 8 |
| 3 | John | 8 | 2 | 6 |
+----+----------+------+-----------+
Any help how to achieve this result ?

The main thing you need is the analytic version of sum. Also, try not to use Oracle keywords (like date) as column names.
-- sample data
with ex as (select 1 as id, 'John' as name, 1 as used, to_date('01/01/2018','mm/dd/yyyy') as date1 from dual
union select 2 as id, 'John' as name, 2 as used, to_date('01/03/2018','mm/dd/yyyy') from dual
union select 3 as id, 'John' as name, 2 as used, to_date('01/05/2018','mm/dd/yyyy') from dual)
-- main query
select id,
name,
11-sum(used) over (partition by name order by date1) + used as days,
used,
11-sum(used) over (partition by name order by date1) as left
from ex;
Output:
ID NAME DAYS USED LEFT
---------- ---- ---------- ---------- ----------
1 John 11 1 10
2 John 10 2 8
3 John 8 2 6

Related

Count Max number of day continious overdraff

Date | Account | Amount | Count max number of day continuous < 0 |
1 | 1001 | 100 | 0 |
2 | 1001 | -100 | 1 |
3 | 1001 | -100 | 2 |
4 | 1001 | 100 | 2 |
5 | 1001 | -100 | 2 |
6 | 1001 | -100 | 2 |
7 | 1001 | -100 | 3 |
8 | 1001 | -100 | 4 |
9 | 1001 | 100 | 4 |
I have sample data. I want have column "Count max number of day continuous < 0". How i can select it in database oracle
In order to find continuous periods you can use Tabibitosian method. Then use analytical count and finally max:
select date_, account, amount,
max(cnt) over (partition by account order by date_) max_overdraft_period
from (
select date_, account, amount,
count(case when amount <= 0 then 1 end)
over (partition by account, grp order by date_) cnt
from (
select date_, account, amount,
date_ - sum(case when amount <= 0 then 1 else 0 end)
over (partition by account order by date_) grp
from t ))
demo
I assumed that dates are continuous, if not then use row numbering at first.

Get all rows from a table having a particular column value but ordered by different column value

I am having trouble formulating this question, so I would give an example to demonstrate. Consider my table as,
CREATE TABLE ABC
(
PID NUMBER(10,0) NOT NULL,
DISP_COL VARCHAR2(100 BYTE),
VAL_COL VARCHAR2(20 BYTE),
ORD_COL1 NUMBER(5,2),
ORD_COL2 NUMBER(5,2),
CONSTRAINT PK_PID PRIMARY KEY
(
PID
)
);
And the data I have is,
PID | DISP_COL | VAL_COL | ORD_COL1 | ORD_COL2
----------------------------------------------
1 | DISP1 | VAL1 | 1 | 14
2 | DISP2 | VAL26 | 2 | 22
3 | DISP1 | VAL8 | 1 | 17
4 | DISP1 | VAL56 | 1 | 9
5 | DISP2 | VAL9 | 2 | -10
6 | DISP3 | VAL12 | 2 | 20
7 | AISP1 | VAL7 | 2 | -3
Now based on the descending ordering of ORD_COL1, ORD_COL2, I want to get the unique DISP_COL values and then all rows of that DISP_COL value to follow. So my data should like,
PID | DISP_COL | VAL_COL | ORD_COL1 | ORD_COL2
----------------------------------------------
2 | DISP2 | VAL26 | 2 | 22
5 | DISP2 | VAL9 | 2 | -10
6 | DISP3 | VAL12 | 2 | 20
7 | AISP1 | VAL7 | 2 | -3
3 | DISP1 | VAL8 | 1 | 17
1 | DISP1 | VAL1 | 1 | 14
4 | DISP1 | VAL56 | 1 | 9
A simple ORDER BY ORD_COL1 DESC, ORD_COL2 DESC does get me the order I want DISP_COL to occur but then I want the same valued rows to follow that.
I am kind of new to oracle and pl/sql, so all help is appreciated. Thanks in advance.
SELECT * FROM ABC ORDER BY ORD_COL1 DESC, DISP_COL ASC, ORD_COL2 DESC;
http://sqlfiddle.com/#!4/40401/18
You will need to order by the DISP_COL in ASC in order to get the result you want. See the updated fiddle and the code above. This will give you what you want from you question.
The following query worked (http://sqlfiddle.com/#!4/c340b/2/0)
SELECT A1.* FROM (SELECT * FROM ABC) A1 INNER JOIN
(SELECT DISP_COL, MAX(ORD_COL1) COL1, MAX(ORD_COL2) COL2 FROM ABC
GROUP BY DISP_COL
ORDER BY COL1 DESC, COL2 DESC) A2 ON (A1.DISP_COL = A2.DISP_COL)
ORDER BY A2.COL1 DESC, A2.COL2 DESC, A2.DISP_COL, A1.ORD_COL1 DESC,
A1.ORD_COL2 DESC;

max() issue in Oracle SQL [duplicate]

This question already has answers here:
Fetch the rows which have the Max value for a column for each distinct value of another column
(35 answers)
Closed 8 years ago.
I'm using Oracle SQL and i need some help with max() function.
I have the following table:
ID | Type | Price | Quantity
1 | A | 10 | 2
2 | B | 5 | 5
3 | C | 10 | 3
4 | A | 8 | 7
5 | A | 6 | 9
6 | A | 7 | 5
7 | B | 15 | 3
8 | A | 20 | 4
9 | A | 3 | 7
10 | B | 11 | 8
I need to aggregate the table by Type column. For each group of Type (A, B, C), i need to select the price and the quantity of max(id).
I this case:
ID | Type | Price | Quantity
9 | A | 3 | 7
10 | B | 11 | 8
3 | C | 10 | 3
Any Suggestion?
max won't help you with this. You can use the row_number partitioning function.
select id, type, price, quantity
from
(
select yourtable.*,
row_number() over (partition by type order by id desc) rn
from yourtable
) v
where rn = 1
Something like this:
Select t.* From
(Select Max(ID) As ID From Table
Group By Type) tmp
Join Table t On t.ID = tmp.ID

Oracle select two (or more) adjacent rows having the same value for a given column

How do I do the following in Oracle:
I have a (simplified) table:
+-----+-----+-----+
| a | b | ... |
+-----+-----+-----+
| 1 | 7 | ... |
| 2 | 5 | ... |
| 1 | 7 | ... |
+-----+-----+-----+
Where a functions as a unique identifier for a person, and b is the field I am interested in matching across rows. How do I construct a query that basically says "give me the person-ID's where the person has multiple b values (i.e., duplicates)"?
So far I have tried:
SELECT a FROM mytable GROUP BY a HAVING COUNT(DISTINCT b) > 1;
This feels close except it just gives me the user IDs where the user has multiple unique b's, which I suspect is coming from the DISTINCT part, but I'm not sure how to change the query to achieve what I want.
Try
group by a,b having count(b) > 1
Yours would count 7,5,7 as 2 (one 7, one 5). This one one will count total Bs in any grouping, so you'll get 1,7 - > 2 and 1,5 -> 1
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE mytable ( a, b ) AS
SELECT LEVEL, LEVEL FROM DUAL CONNECT BY LEVEL <= 2000
UNION ALL
SELECT LEVEL *2, LEVEL * 2 FROM DUAL CONNECT BY LEVEL <= 1000;
Query 1:
WITH data AS (
SELECT a
FROM mytable
GROUP BY a
HAVING COUNT(b) > COUNT( DISTINCT b )
ORDER BY a
),
numbered AS (
SELECT a,
ROWNUM AS rn
FROM data
)
SELECT a
FROM numbered
WHERE rn <= 20
Results:
| A |
|----|
| 2 |
| 4 |
| 6 |
| 8 |
| 10 |
| 12 |
| 14 |
| 16 |
| 18 |
| 20 |
| 22 |
| 24 |
| 26 |
| 28 |
| 30 |
| 32 |
| 34 |
| 36 |
| 38 |
| 40 |

SQL bring back highest sum of rows

I'm looking to calculate the highest basket in my set of data but I can't get my head around how I should do it.
I have data like:
OrderID | CustomerID | BasketID | ProductID | Price
1 | 1 | 1 | 221 | 10
2 | 1 | 1 | 431 | 123
3 | 1 | 2 | 761 | 44
4 | 2 | 3 | 12 | 54
5 | 2 | 3 | 102 | 78
6 | 3 | 4 | 111 | 98
7 | 3 | 4 | 41 | 45
8 | 3 | 5 | 65 | 66
9 | 4 | 6 | 32 | 47
10 | 4 | 6 | 118 | 544
Sorry if it seems quite messy.
But I can easily get the SUM with an obvious
SELECT SUM([Price]), BasketID, CustomerID FROM table
GROUP BY BasketID, CustomerID
But how can I filter the list for only the highest priced Basket ID for that CustomerID
Thanks
You can use a CTE (Common Table Expression) with the ROW_NUMBER function:
;WITH HighestPricePerCustomerAndBasket AS
(
SELECT
ID, UserID, ClassID, SchoolID, Created,
ROW_NUMBER() OVER(PARTITION BY BasketID,CustomerID ORDER BY Price DESC) AS 'RowNum'
FROM dbo.YourTable
)
SELECT
[Price], BasketID, CustomerID
FROM HighestPricePerCustomerAndBasket
WHERE RowNum = 1
This CTE "partitions" your data by BasketID,CustomerID, and for each partition, the ROW_NUMBER function hands out sequential numbers, starting at 1 and ordered by Price DESC - so the first row (highest price) gets RowNum = 1 (for each BasketID,CustomerID "partition") which is what I select from the CTE in the SELECT statement after it.
SELECT *
FROM (SELECT *,
DENSE_RANK() OVER (PARTITION BY CustomerID ORDER BY BasketTotal DESC) AS RNK
FROM (SELECT Sum(Price) AS BasketTotal,
BasketID,
CustomerID
FROM Order a
GROUP BY BasketID,
CustomerID
) a
) b
WHERE RNK = 1
I managed to conjure something up that worked.

Resources