Group matching timestamps into buckets and summarize count - kql

I'm looking for a query that would return 3 numbers for each unique timestamp from the table below. For each timestamp, the count of entries below some fixed threshold, the count above another threshold, and the count between.
database entries
The result would look like this
what I want to return
I think I can get at least one of the three counts with the following, but I can't figure out how to get all three to return:
| where TimestampId > ago(4h)
| project aboveCount = Value > 75
| summarize count()

// Sample data generation. Not part of the solution.
let t = materialize(range Id from 1 to 100 step 1 | extend Timestamp = bin(ago(1h * rand()), 15m), Value = rand(100));
// Solution starts here.
let low_threshold = 25;
let high_threshold = 75;
t
| summarize aboveCount = countif(Value > high_threshold)
,underCount = countif(Value < low_threshold)
,betweenCount = countif(Value between (low_threshold .. high_threshold))
by Timestamp
Timestamp
aboveCount
underCount
betweenCount
2023-01-20T14:00:00Z
6
6
9
2023-01-20T14:15:00Z
8
6
12
2023-01-20T14:30:00Z
4
4
11
2023-01-20T14:45:00Z
6
9
10
2023-01-20T15:00:00Z
1
0
8
Fiddle

Related

How can I calculate user session time from heart beat data in Presto SQL?

I'm currently recording when user's are active via a heart beat. It's stored in a table like so:
User ID
Minute of Day
1
3
1
4
1
5
1
8
1
9
2
2
2
3
2
4
User ID 1 is active from 3 to 5 but then is inactive from 6 to 7 and then becomes active again from 8 to 9.
User ID 1 was active for 3 minutes: (5-3 + 9-8) = 3
User ID 2 was active for 2 minutes: 4-2 = 2
How can I calculate this using a SQL (Presto) query?
Output should be like so:
User ID
Total Minutes
1
3
2
2
You may try the following which uses the lag function to determine active periods (diff = 1) before summing them
SELECT
USERID,
SUM(diff) as TotalMinutes
FROM (
SELECT
UserId,
(MinuteofDay - LAG(MinuteofDay,1,MinuteofDay) OVER (PARTITION BY UserId ORDER BY MinuteofDay)) as diff
FROM
my_table
) t
WHERE
diff = 1
GROUP BY
UserID;
userid
TotalMinutes
1
3
2
2
View on DB Fiddle

finding rows against summed value of specific id's in sql

I have a table like below--
Id| Amount|DateAdded |
--|-------|-----------|
1 20 20-Jun-2018
1 10 05-Jun-2018
1 4 21-May-2018
1 5 15-May-2018
1 15 05-May-2018
2 25 15-Jun-2018
2 25 12-Jun-2018
2 65 05-Jun-2018
2 65 20-May-2018
Here If I sum up the Amount of Id = 1 then I will get 54 as the sum result. I want to find those rows of Id = 1 whose sum is not greater then exact 35 or any given value
In case of given value 35 the expected Output for id = 1 should be--
Id| Amount|DateAdded |
--|-------|-----------|
1 20 20-Jun-2018
1 10 05-Jun-2018
1 4 21-May-2018
1 5 15-May-2018
In case of given value 50 the expected Output for Id = 2 should be--
Id| Amount|DateAdded |
--|-------|-----------|
2 25 15-Jun-2018
2 25 12-Jun-2018
You would use a cumulative sum. To get all the rows:
select t.*
from (select t.*,
sum(amount) over (partition by id order by dateadded) as running_amount
from t
) t
where t.running_amount - amount < 35;
To get just the row that passes the mark:
where t.running_amount - amount < 35 and
t.running_amount >= 35

Find Value in Pivoted LookupTable

I'm trying to figure out the best way to query from a pivoted lookup table.
Ideally, you'd have a look up table with 3 columns
min, max, value
1, 2, a
2, 3, b
3, 4, c
here you can write code to pull the correct output:
select value from table
where input >= min and input < max
so if input = 1.5, then value = a and if input = 2.5, value = b. As the rows are disjoint,
However, our table has to be constructed in the following manner as this is a janky one off situation.
1,2,3,4
a,b,c,-
How would I create a query that would find the value in this type of table?
Thanks for looking!
However, our table has to be constructed in the following manner as
this is a janky one off situation.
You have two options:
Unpivot this table and then query from a result of this subquery in the same manner SELECT value FROM ( subquery ) ...:
SELECT 1 as min, 2 as max, "1" as value FROM table1
UNION ALL
SELECT 2 as min, 3 as max, "2" asvalue FROM table1
Union All
SELECT 3 as min, 4 as max, "3" asvalue FROM table1
Demo: http://sqlfiddle.com/#!17/b6b4d/2
| min | max | value |
|-----|-----|-------|
| 1 | 2 | a |
| 2 | 3 | b |
| 3 | 4 | c |
You can create a view using the above query and run queries against this view.
Assumming that there is only 1 row in this table- build a queries like this one:
SELECT CASE
WHEN input >=1 AND input < 2 THEN "1"
WHEN input >=2 AND input < 3 THEN "2"
WHEN input >=3 AND input < 4 THEN "3"
END As value
FROM Table1
I believe you are looking for a CASE WHEN statement
Select case when min >= 1 and max <3 then 'A'
when min >= 2 and max <4 then 'B'
when min >= 3 and max <5 then 'C'
else NULL
end Value
From table
Hope this helps

Update row based on value of multiple other rows in Oracle SQL

I want to find the rows which are similar to each other, and update a field if a row has any similar row. My table looks like this:
OrderID | Price | Minimum Number | Maximum Number | Volume | Similar
1 45 2 10 250 0
2 46 2 10 250 0
3 60 2 10 250 0
"Similar" in this context means that the rows that have same Maximum Number, Minimum Number, and Volume. Prices can be different, but the difference can be at most 2.
In this example, orders with OrderID of 1 and 2 are similar, but 3 has no similar row (since even if it has same Minimum Number, Maximum Number, and Volume, but its price is not within 2 units from orders 1 and 2).
Then, I want to update the filed "Similar" for orders 1 and 2 from the default value (0) to 1. So, the output for the example above would be:
OrderID | Price | Minimum Number | Maximum Number | Volume | Similar
1 45 2 10 250 1
2 46 2 10 250 1
3 60 2 10 250 0
Here is one method that is ANSI standard SQL that will work in most databases, including Oracle. It implements the logic that you set out using a correlated subquery:
update table t
set similar = 1
where exists (select 1
from table t2
where t2.minimum = t.minimum and
t2.maximum = t.maximum and
t2.volume = t.volume and
abs(t2.price - t.price) <= 2 and
t2.OrderId <> t.OrderId
);
EDIT:
It occurs to me that the "similar" field might be the minimum OrderId of the similar fields. You can extend the above idea to:
update table t
set similar = (select min(orderId)
from table t2
where t2.minimum = t.minimum and
t2.maximum = t.maximum and
t2.volume = t.volume and
abs(t2.price - t.price) <= 2 and
t2.OrderId <> t.OrderId
)
where exists (select 1
from table t2
where t2.minimum = t.minimum and
t2.maximum = t.maximum and
t2.volume = t.volume and
abs(t2.price - t.price) <= 2 and
t2.OrderId <> t.OrderId
);
Although if this were the case, the default value should be NULL and not 0.

Inserting a new indicator column to tell if a given row maximizes another column in SQL

I currently have a table in SQL that looks like this
PRODUCT_ID_1 PRODUCT_ID_2 SCORE
1 2 10
1 3 100
1 10 3000
2 10 10
3 35 100
3 2 1001
That is, PRODUCT_ID_1,PRODUCT_ID_2 is a primary key for this table.
What I would like to do is use this table to add in a row to tell whether or not the current row is the one that maximizes SCORE for a value of PRODUCT_ID_1.
In other words, what I would like to get is the following table:
PRODUCT_ID_1 PRODUCT_ID_2 SCORE IS_MAX_SCORE_FOR_ID_1
1 2 10 0
1 3 100 0
1 10 3000 1
2 10 10 1
3 35 100 0
3 2 1001 1
I am wondering how I can compute the IS_MAX_SCORE_FOR_ID_1 column and insert it into the table without having to create a new table.
You can try like this...
Select PRODUCT_ID_1, PRODUCT_ID_2 ,SCORE,
(Case when b.Score=
(Select Max(a.Score) from TableName a where a.PRODUCT_ID_1=b. PRODUCT_ID_1)
then 1 else 0 End) as IS_MAX_SCORE_FOR_ID_1
from TableName b
You can use a window function for this:
select product_id_1,
product_id_2,
score,
case
when score = max(score) over (partition by product_id_1) then 1
else 0
end as is_max_score_for_id_1
from the_table
order by product_id_1;
(The above is ANSI SQL and should run on any modern DBMS)