Cosmos DB select with where clause with max date - sql

I want to select item with max date.
I have select:
select d.MaxDate from (select max(c.ChangedDateTime) MaxDate FROM c WHERE AND c.IsLatest = true) d
and the result is:
[
{
"MaxDate": "2020-07-16 12:23:57"
}
]
And now I want to select row with max date:
select * FROM c WHERE IsLatest = true
WHERE c.ChangedDateTime = (select d.MaxDate from (select max(c.ChangedDateTime) MaxDate
FROM c WHERE AND c.IsLatest = true) d)
Result is empty, it should return one row with the date 2020-07-16 12:23:57
When I do select like that:
select * from c where c.IsLatest = true AND c.ChangedDateTime = '2020-07-16 12:23:57'
it returns exactly one row which I want to have, so I think that there is something wrong with subselect because it returns array with object [{"MaxDate": "2020-07-16 12:23:57"}]

How about just selecting one row after sorting?
SELECT *
FROM c
WHERE IsLatest = true
ORDER BY c.ChangedDateTime
OFFSET 0 LIMIT 1;

Related

SQL - How to get a duplicate column based on the value of another column

I have a query that return values ​​based on a boolean column: if the id_crsp includes a boolean true AND false, then it is selected.
Values ​​of id_crsp that have only a true or false value are not selected.
From this result, I would like to sort the id_crsp which have duplicates, and select only the one with the oldest date
Database values :
id
idcrsp
date
boolean
1
100
11-2022
true
2
100
07-2022
false
3
200
06-2022
false
4
300
09-2022
true
5
300
08-2022
false
6
400
10-2022
false
7
100
01-2022
false
8
100
02-2022
false
My actual request :
SELECT true_table.* FROM mydb as true_table
INNER JOIN
(SELECT * FROM mydb WHERE requalif=TRUE) as false_table
ON true_table.idcrsp = false_table.idcrsp
AND true_table.requalif = FALSE;
This return :
id
idcrsp
date
boolean
8
100
02-2022
false
7
100
01-2022
false
2
100
07-2022
false
5
300
08-2022
false
I would like to enrich my request in order to have only two lines:
id 5
id 7 (which has duplicates of id_crsp and which has the oldest date).
Thanks for your help !
using your original query could you just add row_number and partition it by the idcrsp and then order by date descending. then just pick the rows where rn = 1
select * from
(SELECT true_table.*, row_number() over (partition by id_crsp order by date desc) rn FROM mydb as true_table
INNER JOIN
(SELECT * FROM mydb WHERE requalif=TRUE) as false_table
ON true_table.idcrsp = false_table.idcrsp
AND true_table.requalif = FALSE)
where rn = 1
How to get, from this last reponse/request :
select * from
(SELECT true_table.*, row_number() over (partition by id_crsp order by date desc) rn FROM mydb as true_table
INNER JOIN
(SELECT * FROM mydb WHERE requalif=TRUE) as false_table
ON true_table.idcrsp = false_table.idcrsp
AND true_table.requalif = FALSE)
where rn = 1
the idcrsp, the date for the min false boolean value, AND the date for the true boolean value wich the most recent date ??
Thank's

How to SELECT WHERE EXISTS in multi table?

I have 3 tables:
/test/table1:
Columns: doc_id, anotherID, value1
/test/table2:
Columns: anotherID, value1
/test/table3
Columns: doc_id, value2
I want to select the data of /test/table1 with 2 conditions. One condition in /test/table2 and another one in /test/table3.
So I select my data in one table with one condition like that:
SELECT doc_id, anotherID FROM /test/table1 AS d
INTO CORRESPONDING FIELDS OF TABLE #ct_document
WHERE EXISTS ( SELECT * FROM /test/table2 AS a
WHERE value1 < #iv_value1 AND a~value1 = d~value1_id ).
It selects the content as I expect. But now I want to add a condition, to only select this data but only where /test/table3~value2 = 2.
To do that, I do:
SELECT doc_id, anotherID FROM /test/table1 AS d
INTO CORRESPONDING FIELDS OF TABLE #ct_document
WHERE EXISTS ( SELECT * FROM /test/table2 AS a
WHERE value1 < #iv_value1 AND a~value1 = d~value1_id )
AND EXISTS ( SELECT * FROM /test/table3 AS e
WHERE e~value2 = 2 ).
When I do that, I have the same content as before... It doesn't take my second condition.
What don't I understand ?
The condition EXISTS ( SELECT * FROM /test/table3 AS e WHERE e~value2 = 2 ) is always evaluated to TRUE if there's at least one line in /test/table3 with e~value2 = 2, whatever the content of the table /test/table1.
To make it evaluated to TRUE or FALSE according to /test/table1 (alias d), you should add the condition AND e~doc_id = d~doc_id, like this:
...
AND EXISTS ( SELECT * FROM /test/table3 AS e
WHERE e~value2 = 2 AND e~doc_id = d~doc_id ).

Check if all rows are the same

I have a select query that returns multiple rows, and I want to check if all rows are the same. So something like this:
anything_other_than(123) in (select id from foo)
So, if select id from foo returns 111,222,123,333 the statement above is false, and if select id from foo returns 123,123,123 it's true. How can I achieve this?
A simple solution is to use the = ALL operator:
SELECT 123 = ALL (SELECT id FROM foo);
This solution also stop scanning the result as soon as the first non-matching value is found.
Another option is to use EXISTS with a where condition:
select not exists (select *
from the_table
where id <> 123);
Run this:
select count(distinct id) = 1 and count(*) > 1 from foo;
count(distinct id) will return 1 if all the rows are the same
and count(*) will return the total number of rows.
If this returns true then you have more than 1 rows and all the rows are the same.
You can use something like this -
select x, IF(x > 1, "FALSE", "TRUE") from
(SELECT count(distinct(A.id)) as x FROM foo as A) as B;
Do refer this https://www.w3schools.com/sql/func_mysql_if.asp

SQL Subtract first row from all selected rows

Is there a way to subtract the value of the first selected row from all rows ? So if I have
t = 1, v = 500
t = 2, v = 800
t = 3, v = 1200
I would get
t = 1, v = 0
t = 2, v = 300
t = 3, v = 700
I'm always looking for a portable solution but a Postgres solution works just the same :-)
Thank you.
SELECT v - FIRST_VALUE(v) OVER (ORDER BY t)
FROM mytable
ORDER BY
t
Something like this may work
SELECT mt2.t, mt2.v - mt1.v AS v
FROM MyTable mt1
CROSS JOIN MyTable mt2
WHERE mt1.t = 1
Most portable way without using window functions:
select v - first
from
mytable,
(select v as first from mytable order by t limit 1) as inner
order by t

T-sql problem with running sum

I am trying to write T-sql script which will find "open" records for one table
Structure of data is following
Id (int PK) Ts (datetime) Art_id (int) Amount (float)
1 '2009-01-01' 1 1
2 '2009-01-05' 1 -1
3 '2009-01-10' 1 1
4 '2009-01-11' 1 -1
5 '2009-01-13' 1 1
6 '2009-01-14' 1 1
7 '2009-01-15' 2 1
8 '2009-01-17' 2 -1
9 '2009-01-18' 2 1
According to my needs I am trying to show only records after last sum for every one articles where 0 sorting by date of last running sum of zero value. So I am trying to abstract (show) records 5 and 6 for Art_id=1 and record 9 for art_id=2. I am using MSSQL2005 and my table has around 30K records with 6000 distinct values of ART_ID.
In this solution I simply want to find all the rows where there isn't a subsequent row for that Art_id where the running sum was 0. I am assuming we can use the ID as a better tiebreaker than TS, since two rows can come in with the same timestamp but they will get sequential identity values.
;WITH base AS
(
SELECT
ID, Art_id, TS, Amount,
RunningSum = Amount + COALESCE
(
(
SELECT SUM(Amount)
FROM dbo.foo
WHERE Art_id = f.Art_id
AND ID < f.ID
)
, 0
)
FROM dbo.[table name] AS f
)
SELECT ID, Art_id, TS, Amount
FROM base AS b1
WHERE NOT EXISTS
(
SELECT 1
FROM base AS b2
WHERE Art_id = b1.Art_id
AND ID >= b1.ID
AND RunningSum = 0
)
ORDER BY ID;
Complete working query:
SELECT
*
FROM TABLE_NAME E
JOIN
(SELECT
C.ART_ID,
MAX(TS) MAX_TS
FROM
(SELECT
ART_ID,
TS,
COALESCE((SELECT SUM(AMOUNT) FROM TABLE_NAME B WHERE (B.Art_id = A.Art_id) AND (B.Ts < A.Ts)),0) ROW_SUM
FROM TABLE_NAME A) C
WHERE C.ROW_SUM = 0
GROUP BY C.ART_ID) D
ON
(D.ART_ID = E.ART_ID) AND
(E.TS >= D.MAX_TS)
First we calculate running sums for every row:
SELECT
ART_ID,
TS,
COALESCE((SELECT SUM(AMOUNT) FROM TABLE_NAME B WHERE (B.Art_id = A.Art_id) AND (B.Ts < A.Ts)),0) ROW_SUM
FROM TABLE_NAME A
Then we look for last article with 0:
SELECT
C.ART_ID,
MAX(TS) MAX_TS
FROM
(SELECT
ART_ID,
TS,
COALESCE((SELECT SUM(AMOUNT) FROM TABLE_NAME B WHERE (B.Art_id = A.Art_id) AND (B.Ts < A.Ts)),0) ROW_SUM
FROM TABLE_NAME A) C
WHERE C.ROW_SUM = 0
GROUP BY C.ART_ID
You can find all rows where the running sum is zero with:
select cur.id, cur.art_id
from #articles cur
left join #articles prev
on prev.art_id = cur.art_id
and prev.id <= cur.id
group by cur.id, cur.art_id
having sum(prev.amount) = 0
Then you can query all rows that come after the rows with a zero running sum:
select a.*
from #articles a
left join (
select cur.id, cur.art_id, running = sum(prev.amount)
from #articles cur
left join #articles prev
on prev.art_id = cur.art_id
and prev.ts <= cur.ts
group by cur.id, cur.art_id
having sum(prev.amount) = 0
) later_zero_running on
a.art_id = later_zero_running.art_id
and a.id <= later_zero_running.id
where later_zero_running.id is null
The LEFT JOIN in combination with the WHERE says: there can not be a row after this row, where the running sum is zero.