how long an amount have been less than 200 - sql

I would need to determine how long amounts have been less than 200.
My dataset looks like
Id user time amount max_amount
25 3618 1 0 1
25 3618 1 17040 3
25 3618 1 30 2
27 4281 1 0 1
27 4281 1 14188 3
27 4281 1 17372 4
27 4281 1 190 2
And so on
The code to generate it is the following:
Select t2.id, t2.user, t1.time, sum(t1.amount_amt as float) / (t1.eur_amt as float) as amount,
rank () over (partition by t2.user order by amount) max_amount
From table1
Inner join table2 as t2
on t1.user=t2.user
Group by 1,2,3
My expected output would be
Id user time spent
25 3618 1 2
27 4281 1 2
How could I get this result?

I think you just want filtering and aggregation:
select id, user, time, count(*)
from t
where amount < 200
group by id, user, time;
If that table is generated by the code in the question, you can just use a CTE before the above query:
with t as (
<query>
)

Related

How to find missing Number along with the numbers present in table in Oracle

I am trying to fetch data for one of my clients, but there are missing tokens in his data. I tried the below query for fetching the missing data and inserting into one dump table, but would like to find a more optimized way where I find the missing tokens along with the token's present in the table.
SELECT MinToken + 1 Level
FROM (SELECT Min(Token) AS MINTOKEN, MAX(Token) AS MAXTOKEN
FROM dmp_SellerOrders
Where OrderNo = 1
AND TradeDate = '27-Oct-20')
CONNECT BY LEVEL < MAXTOKEN - MINTOKEN
MINUS
SELECT TOKEN
FROM dmp_SellerOrders
Where (OrderNo, TranserialNo) IN (SELECT OrderNo, MAX(TranserialNo)
FROM dmp_SellerOrders
GROUP BY OrderNo)
AND TradeDate = '27-Oct-20';
Actual Data in Table looks like this,
Original Order OrderNo TranserialNo Token Qty Price
1 1 25 100 100
1 1 26 100 100
1 1 27 100 100
1 1 28 100 100
1 1 30 100 100
1 1 31 100 100
Order Price Modified OrderNo TranserialNo Token Qty Price
1 2 25 100 200
1 2 26 100 200
1 2 27 100 200
1 2 28 100 200
1 2 30 100 200
1 2 31 100 200
I need data to show by grouping Qty, as show below,
OrderNo MinToken MaxToken Qty Price
1 25 28 100 200
1 29 29 0 0
1 30 31 100 200
But if I group qty then I get below out,
OrderNo MinToken MaxToken Qty Price
1 25 31 100 200
1 29 29 0 0
Can any one please help me, how can I get the output as expected.
Regards,
Mehul
Here a simplified solution without orderNo and TradeDate to demonstrate the concept.
You perform following steps in subsequent subqueries
get all tokens and outer join to the order table to get a complete sequence
find the LAG of the qty column
set grp_id to 1 if there is a break. i.e. if the previos qty is null and the current not null or vice versa - else to 0
cummulate the grp_id using analytic form of SUM
here the result with the sample data
TOKEN QTY PRICE QTY_LAG GRP_ID CUM_GRP_ID
---------- ---------- ---------- ---------- ---------- ----------
25 100 100 1 1
26 100 100 100 0 1
27 100 100 100 0 1
28 100 100 100 0 1
29 100 1 2
30 100 100 1 3
The last step is a simple GROUP BY on qty, price with added cummulated group id cum_grp_id which splits the non adjacent groups.
Query
with orders as (
select 25 token, 100 qty, 100 price from dual union all
select 26 token, 100 qty, 100 price from dual union all
select 27 token, 100 qty, 100 price from dual union all
select 28 token, 100 qty, 100 price from dual union all
select 30 token, 100 qty, 100 price from dual union all
select 31 token, 100 qty, 100 price from dual),
tokens as (
select min(token) min_token, max(token) max_token from orders),
all_tokens as (
select min_token - 1 + level token from tokens
connect by level <= max_token - min_token),
grp as (
select
t.token,
o.qty, o.price,
lag(o.qty) over (order by t.token) as qty_lag
from all_tokens t
left outer join orders o
on t.token = o.token),
grp2 as (
select
token, qty, price, qty_lag,
case when qty is null and qty_lag is null or qty is not null and qty_lag is not null then 0 else 1 end as grp_id
from grp),
grp3 as (
select
token, qty, price, qty_lag, grp_id,
sum(grp_id) over (order by token) cum_grp_id
from grp2)
select min(token), max(token), qty, price
from grp3
group by cum_grp_id, qty, price
order by 1
result
MIN(TOKEN) MAX(TOKEN) QTY PRICE
---------- ---------- ---------- ----------
25 28 100 100
29 29
30 30 100 100
Adapt if required by partitioning the analytic function by orderNo and/or tradeDate.

How to use this in sql -- > max(sum (paid * quantity )) to solve a query

How to get the max value order of each customer ?
select num, max(sum(paid*quantity))
from orders join
pizza
using (order#)
group by customer#;
table
num orderN price
-------- --- -------
1 109 30
1 118 25
3 101 30
3 115 27
4 107 23
5 100 17
5 129 16
output req-
num Pnum price
-------- --- -------
1 109 30
3 101 30
4 107 23
5 100 17
You want to select the record having the highest price in each group of nums.
If your RDBMS supports window functions, that's straight forward with ROW_NUMBER() :
SELECT num, pnum, price
FROM (
SELECT t.*, ROW_NUMBER OVER(PARTITION BY num ORDER BY price DESC) rn
FROM mytable t
) x
WHERE rn = 1
Else, you can take the following approach, that uses a NOT EXISTS condition with a correlated subquery to ensure that the record being joined in the one with the highest price for the current num :
SELECT num, pnum, price
FROM mytable t
WHERE NOT EXISTS (
SELECT 1 FROM mytable t1 WHERE t1.num = t.num AND t1.price > t.price
)

SQL - Number of entries needed to reach given value

I need to find how many records it took to reach a given value. I have a table in the below format:
ID Name Time Time 2
1 Campaign 1 7 100
2 Campaign 3 5 165
3 Campaign 1 3 321
4 Campaign 2 610 952
5 Campaign 2 15 13
6 Campaign 2 310 5
7 Campaign 3 0 3
8 Campaign 1 0 610
9 Campaign 1 1 15
10 Campaign 1 54 310
11 Campaign 3 4 0
12 Campaign 2 23 0
13 Campaign 2 8 1
14 Campaign 3 23 1
15 Campaign 3 7 0
16 Campaign 3 5 5
17 Campaign 3 2 66
18 Campaign 3 100 7
19 Campaign 1 165 3
20 Campaign 1 321 13
21 Campaign 1 952 5
22 Campaign 1 13 3
23 Campaign 2 15 610
24 Campaign 2 0 15
25 Campaign 1 100 310
26 Campaign 2 165 0
27 Campaign 3 321 0
28 Campaign 3 952 1
29 Campaign 3 0 1
30 Campaign 3 5 0
I'd like to find out how many entries of 'Campaign 1' there were before the total of Time1 + Time2 was equal to or greater than a given number.
As an example, the result for Campaign 1 to reach 1400 should be 5.
Apologies if I haven't explained this clearly enough - the concept is still a little muddy at the moment.
Thanks
In SQL Server 2012, you can get the row using:
select t.*
from (select t.*, sum(time1 + time2) over (partition by name order by id) as cumsum
from table t
) t
where cumsum >= #VALUE and (cumsum - (time1 + time2)) < #VALUE;
You can get the count using:
select name, count(*)
from (select t.*, sum(time1 + time2) over (partition by name order by id) as cumsum
from table t
) t
where (cumsum - (time1 + time2)) < #VALUE
group by name;
If you are not using SQL Server 2012, you can do the cumulative sum with a correlated subquery:
select name, count(*)
from (select t.*,
(select sum(time1 + time2)
from table t2
where t2.name = t.name and
t2.id <= t.id
) as cumsum
from table t
) t
where (cumsum - (time1 + time2)) < #VALUE
group by name;
A recursive CTE computing a running total should work:
;WITH CTE AS
(
SELECT id,
name,
SUM([time]+[time 2])
OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
AS RunningTotal
FROM Table1
WHERE name = 'Campaign 1'
)
SELECT count(*)+1 AS [Count]
FROM CTE
WHERE RunningTotal < 1400
Note that I added 1 to the count as the query counts the number of rows needed to reach up to, but not including, 1400. Logic dictates that the next row will push the value above 1400.

Query Two Different Table that have same field item

I have two table
Table_A
ID PostId Item Stock Price
1 1 A 30 10
2 1 B 40 20
3 2 A 50 5
4 3 A 50 25
Table_B
ID PostId Item_ID Sold Price
1 1 1 2 20
2 1 2 2 40
3 1 1 1 10
4 2 3 3 15
5 2 3 1 5
I want to queries from above two table that have same 'PostID' and COUNT and SUM some field group by 'PostID', expected output would be like this
Output
ID PostId Total Item Total Stock Total Buyer(s) Total Sold Total Price
1 1 2 70 3 5 70
I've try to JOIN it, but result still miss calculate
SELECT Table_A.PostId AS PostId, COUNT(Table_A.Item) AS Total_Item, SUM(Table_A.stock) AS Total_Stock, COUNT(Table_B.Item_ID) AS total_buyer, SUM( Table_B.Sold ) AS TotalSold, SUM( Table_B.Price ) AS Total_Price
FROM Table_A
LEFT JOIN Table_B
ON Table_A.PostId = Table_B.PostId
WHERE Table_A.PostId = '1'
GROUP BY Table_A.PostId
LIMIT 0 , 30
Any suggestion for this query problem?? Thank you
SELECT Table_B.PostId AS PostId,
MIN(Table_A.Total_Item) AS Total_Item,
MIN(Table_A.Total_Stock) AS Total_Stock,
COUNT(Table_B.Item_ID) AS total_buyer,
SUM( Table_B.Sold ) AS TotalSold,
SUM( Table_B.Price ) AS Total_Price
FROM Table_B
LEFT JOIN
(
SELECT PostId,
COUNT(Item) AS Total_Item,
SUM(stock) AS Total_Stock
FROM
Table_A
GROUP BY PostId
) Table_A
ON Table_B.PostId=Table_A.PostId
WHERE Table_B.PostId = '1'
GROUP BY Table_B.PostId
LIMIT 0 , 30

Pivot SQL with Rank

Basically i have the following query and i am trying to distinguish only the unique ranks from this:
WITH numbered_rows
as (
SELECT Claim,
reserve,
time,
RANK() OVER (PARTITION BY ClaimNumber ORDER BY time asc) as 'Rank'
FROM (
SELECT cc.Claim,
MAX(csd.time) as time,
csd.reserve
FROM ClaimData csd WITH (NOLOCK)
JOIN Core cc WITH (NOLOCK)
on cc.ClaimID = csd.ClaimID
GROUP BY cc.Claim, csd.Reserve
) as t
)
select *
from numbered_rows cur, numbered_rows prev
where cur.Claim= prev.Claim
and cur.Rank = prev.Rank -1
The results set I get is the following:
Claim reserve Time Rank Claim reserve Time Rank
--------------------------------------------------------------------
11 0 12/10/2012 1 11 15000 5/30/2013 2
34 2000 1/21/2013 1 34 750 1/31/2013 2
34 750 1/31/2013 2 34 0 3/31/2013 3
07 800000 5/9/2013 1 07 0 5/10/2013 2
But what I only want to see the following: (have the Claim 34 Rank 2 removed because its not the highest
Claim reserve Time Rank Claim reserve Time Rank
--------------------------------------------------------------------
11 0 12/10/2012 1 11 15000 5/30/2013 2
34 750 1/31/2013 2 34 0 3/31/2013 3
07 800000 5/9/2013 1 07 0 5/10/2013 2
I think you can do this by just reversing your logic, i.e. order by time DESC, switching cur and prev in your final select and changing -1 to +1 in your final select, then just limiting prev.rank to 1, therefore ensuring that the you only include the latest 2 results for each claim:
WITH numbered_rows AS
( SELECT Claim,
reserve,
time,
[Rank] = RANK() OVER (PARTITION BY ClaimNumber ORDER BY time DESC)
FROM ( SELECT cc.Claim,
[Time] = MAX(csd.time),
csd.reserve
FROM ClaimData AS csd WITH (NOLOCK)
INNER JOIN JOIN Core AS cc WITH (NOLOCK)
ON cc.ClaimID = csd.ClaimID
GROUP BY cc.Claim, csd.Reserve
) t
)
SELECT *
FROM numbered_rows AS prev
INNER JOIN numbered_rows AS cur
ON cur.Claim= prev.Claim
AND cur.Rank = prev.Rank + 1
WHERE prev.Rank = 1;