I’m newbie in Kusto language and I am trying to create a query that calculates the percentage of the total at the unique user level. the ratio column doesn't return any result- maybe I'm doing it wrong :/ is there a better way to do this?
let T2 = T1
|where timesstamp >ago(1m) and variable =='ss'
|summarize col_1 = dcount(user) by bin(timesstamp, 1s)
;
let T3 = T1
|where timesstamp >ago(1m) and variable in ('ss', 'ss1', 'ss2', 'ss3')
|summarize col_2 = dcount(user) by bin(timesstamp, 1s)
;
T3
| join T2 on timesstamp
|extend ratio =tolong(col_1/col_2)*100
you could try this:
let T1 = datatable(timestamp:datetime, variable:string, user:string)
[
datetime(2020-09-03 03:14:35), "ss", "u1",
datetime(2020-09-03 03:14:35), "ss1", "u1",
datetime(2020-09-03 03:14:35), "ss2", "u1",
datetime(2020-09-03 03:14:35), "ss2", "u2",
datetime(2020-09-03 03:14:36), "ss", "u2",
datetime(2020-09-03 03:14:37), "ss", "u2",
datetime(2020-09-03 03:14:37), "ss", "u1",
datetime(2020-09-03 03:14:37), "ss2", "u1",
datetime(2020-09-03 03:14:37), "ss1", "u2",
datetime(2020-09-03 03:14:37), "ss3", "u3",
]
;
let T2 = T1
| where timestamp > ago(10m) and variable == 'ss'
| summarize col_1 = dcount(user) by bin(timestamp, 1s)
;
let T3 = T1
| where timestamp > ago(10m) and variable in ('ss', 'ss1', 'ss2', 'ss3')
| summarize col_2 = dcount(user) by bin(timestamp, 1s)
;
T3
| join T2 on timestamp
| project timestamp, col_1, col_2, ratio = round(100.0 * col_1 / col_2, 2)
--->
| timestamp | col_1 | col_2 | ratio |
|-----------------------------|-------|-------|-------|
| 2020-09-03 03:14:35.0000000 | 1 | 2 | 50 |
| 2020-09-03 03:14:36.0000000 | 1 | 1 | 100 |
| 2020-09-03 03:14:37.0000000 | 2 | 3 | 66.67 |
Related
I have a table that looks like this:
| client_id | program_id | provider_id | date_of_service | data_entry_date | data_entry_time |
| --------- | ---------- | ----------- | --------------- | --------------- | --------------- |
| 2 | 5 | 6 | 02/02/2022 | 02/02/2022 | 0945 |
| 2 | 5 | 6 | 02/02/2022 | 02/07/2022 | 0900 |
| 2 | 5 | 6 | 02/04/2022 | 02/04/2022 | 1000 |
| 2 | 5 | 6 | 02/04/2022 | 02/04/2022 | 1700 |
| 2 | 5 | 6 | 02/04/2022 | 02/05/2022 | 0800 |
| 2 | 5 | 6 | 02/04/2022 | 02/05/2022 | 0900 |
I need to get the most recent date_of_service entered. From the table above, the desired result/row is:
date_of_service = 02/04/2022, data_entry_date = 02/05/2022, data_entry_time = 0900
This resulting date_of_service will be left joined to the master table.
This query mostly works:
SELECT t1.client_id, t1.program_id, t1.provider_id, t2.date_of_service
FROM table1 as t1
WHERE provider_id = '6'
LEFT JOIN
(SELECT client_id, program_id, provider_id, date_of_service
FROM table2) as t2
ON t2.client_id = t1.client_id
AND t2.program_id = t1.program_id
AND t2.provider_id = t1.provider_id
AND t2.date_of_service =
(SELECT MAX(date_of_service)
FROM t2 as t3
WHERE t3.client_id = t1.client_id
AND t3.program_id = t1.program_id
AND t3.provider_id = t1.provider_id
)
)
But it also returns multiple rows whenever there is more than one match on the max(date_of_service).
To solve this, I need to use the max data_entry_date to break any ties whenever there is more than one row that matches the max(date_of_service). Likewise, I also need to use the max data_entry_time to break any ties whenever there is more than one row that also matches the max data_entry_date.
I tried the following:
SELECT t1.client_id, t1.program_id, t1.provider_id, t2.date_of_service
FROM table1 as t1
WHERE provider_id = '6'
LEFT JOIN
(SELECT TOP(1) client_id, program_id, provider_id, date_of_service, data_entry_date, data_entry_time
FROM table2
ORDER BY date_of_service DESC, data_entry_date DESC, data_entry_time DESC
) as t2
ON t2.client_id = t1.client_id
AND t2.program_id = t1.program_id
AND t2.provider_id = t1.provider_id
But I can only get it to return null values for the date_of_service.
Likewise, this:
SELECT t1.client_id, t1.program_id, t1.provider_id, t2.date_of_service
FROM table1 as t1
WHERE provider_id = '6'
LEFT JOIN
(
SELECT TOP(1) client_id AS client_id2, program_id AS program_id2, provider_id AS provider_id2, date_of_service, data_entry_date, data_entry_time
FROM table2 AS t3
JOIN
(SELECT
MAX(date_of_service) AS max_date_of_service
,MAX(data_entry_date) AS max_data_entry_date
FROM table1
WHERE date_of_service = (SELECT MAX(date_of_service) FROM table2)
) AS t4
ON t3.date_of_service = t4.max_date_of_service
AND t3.data_entry_date = t4.max_data_entry_date
ORDER BY data_entry_time
) AS t2
ON t2.client_id2 = t1.client_id
AND t2.program_id2 = t1.program_id
AND t2.provider_id2 = t1.provider_id
... works (meaning it doesn't throw any errors), but it only seems to return null values for me.
I've tried various combinations of MAX, ORDER BY, and multiple variations of JOIN's, but haven't found one that works yet.
I don't know what version my SQL database is, but it doesn't appear to handle window functions like OVER and PARTITION or other things like COALESCE. I've been using DBeaver 22.2.0 to test the SQL scripts.
Based on your what you've provided, looks like you can simply query table2:
SELECT client_id, program_id, provider_id, MAX(date_of_service), MAX(data_entry_date), MAX(data_entry_time)
FROM table2
GROUP BY client_id, program_id, provider_id
If you need to join this result set to table1, just JOIN to the statement above on client_id, program_id, provider_id
Try using below query. This is using just joins and sub query.
SELECT TOP 1 * FROM table1 t1
JOIN (
SELECT
MAX(date_of_Service) AS Max_date_of_Service
,MAX(data_entry_date) AS Max_data_entry_date
FROM table1
WHERE date_of_Service = (SELECT MAX(date_of_Service) FROM table1)
)t2
ON t1.date_of_Service = t2.Max_date_of_Service
AND t1.data_entry_date = t2.Max_data_entry_date
ORDER BY data_entry_time
I have two tables,
[TABLE_1]
| ID1 | ID2 | ID3 |
|-----+-----+-----|
| 200 | 125 | 300 |
| 206 | 128 | 650 |
| 230 | 543 | 989 |
[TABLE_2]
| ID1 | ID2 | ID3 | Date |
|-----+-----+-----+--------|
| 200 | 125 | 300 | 1/1/18 |
| 200 | 125 | 300 | 1/1/19 |
| 206 | 128 | 650 | 1/1/13 |
| 206 | 128 | 650 | 1/2/13 |
| 206 | 128 | 650 | 9/5/05 |
I'm trying to Left Join TABLE_1 to TABLE_2 while filtering the output so only rows where Date is at its maximum for those classifications are displayed. I simplified the data in my tables a little bit, but there's NO overall max date that can be used for all items in the table, the max date is unique to each item.
Desired results on the above example would be:
| ID1 | ID2 | ID3 | Date |
|-----+-----+-----+--------|
| 200 | 125 | 300 | 1/1/19 |
| 206 | 128 | 650 | 1/2/13 |
Here's my latest attempt at the query. It seems a little too complicated as I'm relatively new with SQL and has been running without giving a result for a long time now so I'm afraid it may be in an endless loop somehow:
SELECT DISTINCT *
FROM TABLE_1 t1
LEFT JOIN TABLE_2 t2
ON t1.ID1 = t2.ID1
AND t1.ID2 = t2.ID2
AND t1.ID3 = t2.ID3
WHERE t2.Date = (SELECT MAX(Date) FROM Table_2
WHERE t1.ID1 = t2.ID2
AND t1.ID2 = t2.ID2
AND t1.ID3 = t2.ID3);
Any help on how better to query this will be greatly appreciated, thanks!
Notes: The column names are not identical (I know this would cause an error), I only labeled them like that for simplification.
For your given results, why not just aggregate table 2?
select id1, id2, id3, max(date)
from table2
group by id1, id2, id3;
If you need to filter this only for the triples in table1, then:
select t2.id1, t2.id2, t2.id3, max(t2.date)
from table2 t2 join
table1 t1
on t2.id1 = t1.id1 and t2.id2 = t1.id2 and t2.id3 = t1.id3
group by t2.id1, t2.id2, t2.id3;
So as per the comments, I think the following is the complete code:
SELECT
T1.ID1,
T1.ID2,
T1.ID3,
MAX(T2.DATE) AS DATE
FROM
TABLE1 T1
-- USED LEFT JOIN AS NOT SURE IF THERE IS ATLEAST ONE ROW IN T2 FOR EACH ROW IN T1
LEFT JOIN (
SELECT
ID1,
ID2,
ID3,
MAX(DATE)
FROM
TABLE2
GROUP BY
ID1,
ID2,
ID3
) T2 ON T2.ID1 = T1.ID1
AND T2.ID2 = T1.ID2
AND T2.ID3 = T1.ID3;
Cheers!!
You can also use the WITH statement, preaggregating the entries in table 2:
WITH agg_table_2 AS (
SELECT
ID1
,ID2
,ID3
,MAX(DATE) AS MAX_DATE
FROM TABLE_2
GROUP BY
ID1
,ID2
,ID3
)
SELECT
T1.ID1
,T1.ID2
,T1.ID3
,T2.MAX_DATE
FROM TABLE_1 T1
--LEFT
JOIN TABLE_2 T2
ON T1.ID1 = T2.ID1
AND T1.ID2 = T2.ID2
AND T1.ID3 = T2.ID3
;
Note that I actually commented out the LEFT in JOIN as in your desired output 230, 543, 989 was not present. Uncomment it, if you want to keep that entry with NULL value assigned.
I'm trying to join Table1 to Table2 as shown below:
Table1:
| RecCurr | PayCurr | MTMCurr | TradeID |
|---------|---------|---------|---------|
| USD | CAD | JPY | 1234 |
Table2:
+------+-------+
| Curr | Value |
+------+-------+
| USD | 10 |
| CAD | 11 |
| JPY | 12 |
+------+-------+
Joined table:
+---------+---------+---------+---------+----------+----------+----------+
| RecCurr | PayCurr | MTMCurr | TradeID | RecValue | PayValue | MTMValue |
+---------+---------+---------+---------+----------+----------+----------+
| USD | CAD | JPY | 1234 | 10 | 11 | 12 |
+---------+---------+---------+---------+----------+----------+----------+
So far, the only solution I have is the following:
SELECT T1.RecCurr, T1.PayCurr, T1.MTMCurr, T2.RecValue, T3.PayValue, T4.MTMValue
FROM
(SELECT RecCurr, PayCurr, MTMCurr FROM Table1) T1,
(SELECT RecCurr, RecValue FROM Table2) T2,
(SELECT PayCurr, PayValue FROM Table2) T3,
(SELECT MTMCurr, MTMValue FROM Table2) T4
where T1.RecCurr = T2.RecCurr
and T1.PayCurr = T3.PayCurr
and T4.MTMCurr = T4.MTMCurr
Is there a cleaner solution that doesn't require me to join Table2 3 times with Table1?
NOTE: Following works on ASE; me thinks it should work on SQLAnywhere (and IQ) but I don't have a SQLAnywhere db up and running at the moment ...
If you only want to do a single join to Table2 then you'll need a query that performs a table pivot.
First the setup:
create table Table1
(RecCurr char(3)
,PayCurr char(3)
,MTMCurr char(3)
,TradeID int)
go
insert Table1 values ('USD','CAD','JPY',1234)
go
create table Table2
(Curr char(3)
,Value int)
go
insert Table2 values ('USD',10)
insert Table2 values ('CAD',11)
insert Table2 values ('JPY',12)
go
select * from Table1
go
RecCurr PayCurr MTMCurr TradeID
------- ------- ------- -----------
USD CAD JPY 1234
select * from Table2
go
Curr Value
---- -----------
USD 10
CAD 11
JPY 12
An example query with a single join to Table2:
select T1.RecCurr,
T1.PayCurr,
T1.MTMCurr,
T1.TradeID,
sum(case when T2.Curr = T1.RecCurr then T2.Value else 0 end) as RecValue,
sum(case when T2.Curr = T1.PayCurr then T2.Value else 0 end) as PayValue,
sum(case when T2.Curr = T1.MTMCurr then T2.Value else 0 end) as MTMValue
from Table1 T1,
Table2 T2
where T2.Curr in (T1.RecCurr, T1.PayCurr, T1.MTMCurr)
group by T1.RecCurr, T1.PayCurr, T1.MTMCurr, T1.TradeID
go
RecCurr PayCurr MTMCurr TradeID RecValue PayValue MTMValue
------- ------- ------- ----------- ----------- ----------- -----------
USD CAD JPY 1234 10 11 12
And for those with allergies to comma's (in the FROM clause):
select T1.RecCurr,
T1.PayCurr,
T1.MTMCurr,
T1.TradeID,
sum(case when T2.Curr = T1.RecCurr then T2.Value else 0 end) as RecValue,
sum(case when T2.Curr = T1.PayCurr then T2.Value else 0 end) as PayValue,
sum(case when T2.Curr = T1.MTMCurr then T2.Value else 0 end) as MTMValue
from Table1 T1
join Table2 T2
on T2.Curr in (T1.RecCurr, T1.PayCurr, T1.MTMCurr)
group by T1.RecCurr, T1.PayCurr, T1.MTMCurr, T1.TradeID
go
RecCurr PayCurr MTMCurr TradeID RecValue PayValue MTMValue
------- ------- ------- ----------- ----------- ----------- -----------
USD CAD JPY 1234 10 11 12
There is always a better way to write a query when it has commas in the FROM clause. In addition, the subqueries are unnecessary:
SELECT T1.RecCurr, T1.PayCurr, T1.MTMCurr,
T2r.RecValue, T2p.PayValue, T2m.MTMValue
FROM T1 JOIN
Table2 t2r
ON T2r.RecCurr = T1.RecCurr JOIN
Table2 t2p
ON t2p.PayCurr = t1.PayCurr
Table2 t2m
ON t2m.MTMCurr = t1.MTMCurr;
I have a table like below:
S.No | Item_ID | Item_Revision | Code |
-----+---------+---------------+-------
1. | item1 | 0 | xyz |
2. | item2 | 0 | xyz |
3. | item3 | 0 | xyz |
4. | item1 | 1 | |
5. | item2 | 1 | abc |
6. | item3 | 1 | xyz |
I need to compare the records in the table to find the differences in code in different revisions of the items.
I want the result set as below:
| Item_ID | Code_Revision_0 | Code_Revision_1 |
| item1 | xyz | |
| item2 | xyz | abc |
I am not able to formulate an oracle query for this purpose.
Thanks in advance!
One basic idea is to use join:
select t0.item_id, t0.code as code_0, t1.code as code_1
from t t0 join
t t1
on t0.item_id = t1.item_id and
t0.item_revision = 0 and
t1.item_revision = 1
where t0.code <> t1.code;
However, if the code value is NULL (or an empty string), you need to be more careful:
where t0.code <> t1.code or (t0.code is null and t1.code is not null) or
(t0.code is not null and t1.code is null)
You can use a self join to do this.
select t1.item_id, t1.code code_rev_0, t2.code code_rev_1
from tablename t1
join tablename t2 on t1.item_id=t2.item_id
and t1.item_revision = 0 and t2.item_revision = 1
where nvl(t1.code,'a') <> nvl(t2.code,'a')
Here is a solution that uses the PIVOT operator instead of a self-join. If I am reading the execution plans correctly, this is slightly more efficient (cost of 13 vs. 17 for the join solution) for the input data you provided. You may want to test the two solutions on your actual data to see which works better.
with
input_data ( item_id, item_revision, code ) as (
select 'item1', 0, 'xyz' from dual union all
select 'item2', 0, 'xyz' from dual union all
select 'item3', 0, 'xyz' from dual union all
select 'item1', 1, '' from dual union all
select 'item2', 1, 'abc' from dual union all
select 'item3', 1, 'xyz' from dual
)
select *
from input_data
pivot (max(code) for item_revision in (0 as code_revision_0, 1 as code_revision_1))
where code_revision_0 != code_revision_1
or code_revision_0 is null and code_revision_1 is not null
or code_revision_0 is not null and code_revision_1 is null
;
OUTPUT:
ITEM_ CODE_REVISION_0 CODE_REVISION_1
----- ---------------- ----------------
item1 xyz
item2 xyz abc
2 rows selected.
I'm trying write a query to find records which don't have a matching record in another table.
For example, I have a two tables whose structures looks something like this:
Table1
State | Product | Distributor | other fields
CA | P1 | A | xxxx
OR | P1 | A | xxxx
OR | P1 | B | xxxx
OR | P1 | X | xxxx
WA | P1 | X | xxxx
VA | P2 | A | xxxx
Table2
State | Product | Version | other fields
CA | P1 | 1.0 | xxxx
OR | P1 | 1.5 | xxxx
WA | P1 | 1.0 | xxxx
VA | P2 | 1.2 | xxxx
(State/Product/Distributor together form the key for Table1. State/Product is the key for Table2)
I want to find all the State/Product/Version combinations which are Not using distributor X. (So the result in this example is CA-P1-1.0, and VA-P2-1.2.)
Any suggestions on a query to do this?
SELECT
*
FROM
Table2 T2
WHERE
NOT EXISTS (SELECT *
FROM
Table1 T1
WHERE
T1.State = T2.State AND
T1.Product = T2.Product AND
T1.Distributor = 'X')
This should be ANSI compliant.
In T-SQL:
SELECT DISTINCT Table2.State, Table2.Product, Table2.Version
FROM Table2
LEFT JOIN Table1 ON Table1.State = Table2.State AND Table1.Product = Table2.Product AND Table1.Distributor = 'X'
WHERE Table1.Distributor IS NULL
No subqueries required.
Edit: As the comments indicate, the DISTINCT is not necessary. Thanks!
select * from table1 where state not in (select state from table1 where distributor = 'X')
Probably not the most clever but that should work.
SELECT DISTINCT t2.State, t2.Product, t2.Version
FROM table2 t2
JOIN table1 t1 ON t1.State = t2.State AND t1.Product = t2.Product
AND t1.Distributor <> 'X'
In Oracle:
SELECT t2.State, t2.Product, t2.Version
FROM Table2 t2, Table t1
WHERE t1.State(+) = t2.State
AND t1.Product(+) = t2.Product
AND t1.Distributor(+) = :distributor
AND t1.State IS NULL