In my database I have patient records and in the table have column name Registered_Date in this yyyy-mm-dd format so when I execute query like
SELECT Patient_ID,First_Name,Middle_Name,Last_Name
FROM Patient_Records
WHERE Registered_Date BETWEEN '2019-01-25' AND '2018-10-01'
There is no result...
As you can see the first date is greater than the second date but there is no result, but if the first date is less than the second date it will result all the patient whose registered on the selected date.
Everything works as intended.
From the SQLite documentation :
The BETWEEN operator is logically equivalent to a pair of comparisons. x BETWEEN y AND z is equivalent to x >= y AND x <=z
So if the first date is greater than the second (ie y > z), the condition will always be evaluated as false, no matter what value (x) it is given.
Related
I want to get the 1st, 2nd, 3rd,...largest value of Time in SQL Server 2018's table.
In my code when I get the 3rd largest, if my month condition is 5, it returns correct value. But if my month condition is 4, it returns the max time value not my expected time value ( 3rd ). I don't know why.
My query:
SELECT MAX([Time1].[Time]) FROM [dbo].[index4_MonthChart] as [Time1]
WHERE
Month([Time]) = '4'
AND [Time1].[Time] < ( SELECT MAX([Time2].[Time]) FROM [dbo].[index4_MonthChart] as [Time2]
WHERE
[Time2].[Time] < ( SELECT MAX([Time3].[Time]) FROM [dbo].[index4_MonthChart] as [Time3]))
All my value in table:
When month(time) condition is 5, it returns:
But when month(time) is 4, it always returns the max time value and it is wrong ( The correct time value have to be 2023-04-28 ) :
Very simple. You need to add a where clause in your sub-selects to restrict those to Month= 4 as well. Since there are at least two times greater than 30.04 (IE all the times from May), your current query returns the maximum time for April. This doesn't happen for May, because your data has no values later than May.
I have this problem using SQL where I want to find the closest matched date between two columns. Imagine this is my data-set:
'LY Date' is just last years date of 'Date' column I want to put into the new column 'Closest Date' which 'Date' that the 'LY Date', for each row, is closest to.
Example: the 22-02-2022 has last years date of 21-02-2021. This date is closest to the 15-02-2021 from 'Date' column so I put it in 'Closest Date'
I’ve referred to the columns as ‘DATE.DATE’ and ‘LYDATE.DATE’.
You can start from the LYDATE and obtain the top 1 record from DATE when DATE is sorted descending and only contains items less than ‘LYDATE’. You can then flip the DATE table and obtain the top 1 after filtering out those items less than LYDATE. This will give you the closest date that’s less than what we are looking for and the closest date that’s greater than what we are looking for.
I then calculate the date difference between those two limits to see which has smaller difference, and return the appropriate limit value as ClosestDate.
SELECT
CASE WHEN DATEDIFF(ns,lowerlimit.date, LYDate.date) < DATEDIFF(ns, upperlimit.date, LYDATE.date) THEN lowerlimit.date ELSE upperlimit.date END as ClosestDate
FROM LYDate
OUTER APPLY (SELECT TOP 1 DATE FROM DATE WHERE DATE.DATE < LYDATE.DATE ORDER BY DATE.DATE DESC) lowerlimit
OUTER APPLY (SELECT TOP 1 DATE FROM DATE WHERE DATE.DATE > LYDATE.DATE ORDER BY DATE.DATE ASC) upperlimit
I have a table with the following data.
I am expecting row which needs to be returned is with exp_dt "2020-09-22". But when run below query it returning both the rows. I am not understanding why it is returning the first row also when it has eff_dt "2020-09-19".
select id,cd,eff_dt,exp_dt,post_dt from table
where from_unixtime(unix_timestamp(eff_dt,"yyyy-MM-dd")) <= from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
and from_unixtime(unix_timestamp(exp_dt,"yyyy-MM-dd")) >= from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"));
Is there any issue with my query? I am expecting 2nd row to be returned.
Use < for the comparison to exp_date:
select id,cd,eff_dt,exp_dt,post_dt
from table
where from_unixtime(unix_timestamp('2020-09-21', 'yyyy-MM-dd')) >= from_unixtime(unix_timestamp(eff_dt, 'yyyy-MM-dd')) and
from_unixtime(unix_timestamp('2020-09-22', 'yyyy-MM-dd')) < from_unixtime(unix_timestamp(exp_dt, 'yyyy-MM-dd'))
I reversed the comparison order. I find it easier to follow the logic with the constants first.
Does this capture the edge case of equal same day expiry and solve your problem at the same time?
select id,cd,eff_dt,exp_dt,post_dt from table
where
(from_unixtime(unix_timestamp(eff_dt,"yyyy-MM-dd")) <= from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
and
from_unixtime(unix_timestamp(exp_dt,"yyyy-MM-dd")) > from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
)
or
(from_unixtime(unix_timestamp(eff_dt,"yyyy-MM-dd")) = from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
and
from_unixtime(unix_timestamp(exp_dt,"yyyy-MM-dd")) = from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
)
;
In fact I suspect exp is always >= eff, so maybe only one condition
from_unixtime(unix_timestamp(eff_dt,"yyyy-MM-dd")) <= from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
is enough...?
You do not need from_unixtime(unix_timestamp()) because dates are already in correct format and argument is in the same yyyy-MM-dd format.
The issue in your query is that you are using equal for both eff and exp dates
To find latest record on date use this query:
select id,cd,eff_dt,exp_dt,post_dt from table
where eff_dt <= "2020-09-21"
and exp_dt > "2020-09-21";
There should be no records when eff_dt = exp_dt in SCD2 if you have only date (without time component). dates can be equal only if you are using timestamps, and time is different, in this case convert your argument date to timestamp before checking.
SCD2 should be designed in such way that fact record can be mapped to exactly one record of SCD2.
Let's say I have a table of cases with the column period of type tstzrange (see below)
period
------------------------------------
["2018-06-14 21:19:55.802427+02",)
(1 row)
What I want to do is a query of the type
select count(*) from cases where
current_date is in range (period); # this last part is just pseudocode
I want to count the amount of rows where the current_date (just the day, month, year) equals the upper range of the range. How can I do this?
I looked into upper_inc() but couldn't quite understand how to use it with current_date.
You can use upper to get upper bound timestamp, convert it to date and compare.
SELECT '2018-07-17'::date = upper('[2018-07-16 01:00:00,2018-07-17 06:00:00)'::tstzrange)::date
Table format is as follows:
Date ID subID value
-----------------------------
7/1/1996 100 1 .0543
7/1/1996 100 2 .0023
7/1/1996 200 1 -.0410
8/1/1996 100 1 -.0230
8/1/1996 200 1 .0121
I'd like to apply STDEV to the value column where date falls within a specified range, grouping on the ID column.
Desired output would like something like this:
DateRange, ID, std_v
1 100 .0232
2 100 .0323
1 200 .0423
One idea I've had that works but is clunky, involves creating an additional column (which I've called 'partition') to identify a 'group' of values over which STDEV is taken (by using the OVER function and PARTITION BY applied to 'partition' and 'ID' variables).
Creating the partition variable involves a CASE statement prior where a given record is assigned a partition based on its date falling within a given range (ie,
...
, partition = CASE
WHEN date BETWEEN '7/1/1996' AND '10/1/1996' THEN 1
WHEN date BETWEEN '10/1/1996' AND '1/1/1997' THEN 2
...
Ideally, I'd be able to apply STDEV and the OVER function partitioning on the variable ID and variable date ranges (eg, say, trailing 3 months for a given reference date). Once this works for the 3 month period described above, I'd like to be able to make the date range variable, creating an additional '#dateRange' variable at the start of the program to be able to run this for 2, 3, 6, etc month ranges.
I ended up coming upon a solution to my question.
You can join the original table to a second table, consisting of a unique list of the dates in the first table, applying a BETWEEN clause to specify desired range.
Sample query below.
Initial table, with columns (#excessRets):
Date, ID, subID, value
Second table, a unique list of dates in the previous, with columns (#dates):
Date
select d.date, er.id, STDEV(er.value)
from #dates d
inner join #excessRet er
on er.date between DATEADD(m, -36, d.date) and d.date
group by d.date, er.id
order by er.id, d.date
To achieve the desired next step referenced above (making range variable), simply create a variable at the outset and replace "36" with the variable.