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
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
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 ).
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
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
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.