PLSQL 'IN' Operator - sql

I'm trying to select rows based on a range of 'dates' determined by the following PLSQL query, which currently delivers the results I need - being the 'date' object of the last 10 weeks of the day of the week when the script is run. Eg. running it on the 22th of May would yield, 15th May, 8th May and so on.
SELECT SYSDATE-(level*7) as DateRange
FROM DUAL
CONNECT BY LEVEL <=10
This generates a list of dates. Then I try and combine this with a parent select statement to get rows with the dates outputted by the above that are in the 'DAY' (of Oracle type DATE) column.
SELECT * FROM NEM_RM16
WHERE NEM_RM16.DAY IN (
SELECT SYSDATE-(level*7) as DateRange
FROM DUAL
CONNECT BY LEVEL <=10);
Which gives no results, despite knowing that there are rows that have the dates generated by the above.
I've read that when using the 'IN' operator, values must be enclosed in single quotes, but I'm not sure about how to do this with the query above.
Am I going about this the right way by using the IN operator, or should I be doing a different type of nested query?

use trunc for truncate time component from sysdate
SELECT * FROM NEM_RM16
WHERE NEM_RM16.DAY IN (
SELECT trunc(SYSDATE)-(level*7) as DateRange
FROM DUAL
CONNECT BY LEVEL <=10);

Maybe the format of the date returned by nested query does not match with the date format of the column NEM_RM16.DAY
Probably, if the dates are compared after making them of the same format, they will match properly
Like this
SELECT *
FROM NEM_RM16
WHERE TO_DATE(TO_CHAR(NEM_RM16.DAY, 'DD/MM/YYYY'), 'DD/MM/YYYY') IN
(SELECT TO_DATE(TO_CHAR(SYSDATE - (level * 7), 'DD/MM/YYYY'),
'DD/MM/YYYY') as DateRange
FROM DUAL
CONNECT BY LEVEL <= 10);
Hope it helps

Related

How to convert a date to a string

I want yo get only the 'date hours:minutes:seconds' from the Date column
Date
10/11/22 12:14:01,807000000
11/12/22 13:15:46,650000000
29/12/22 14:30:46,501000000
and I want to get a string column with date hours:minutes:seconds
Date_string
10/11/22 12:14:01
11/12/22 13:15:46
29/12/22 14:30:46
I tried this code but it doesn't work:
select*, TO_CHAR(extract(hour from (Date)))||':'||TO_CHAR(extract(minute from (Date)))||':'||TO_CHAR(extract(second from (Date))) as Date_string
from table;
If this is a date column, you could use to_char directly:
SELECT m.*, TO_CHAR(my_date_column, 'dd/mm/yy hh24:mi:ss')
FROM mytable m
You can use REGEX SUBSTRING function to get the date string on the left.
SELECT REGEXP_SUBSTR (Date_string, '[^,]+', 1, 1)
AS left_part
FROM Table1;
where ^, means look for chars that are NOT comma on 1st position
and get the first occurrence (on the left)
Result:
LEFT_PART
10/11/22 12:14:01
11/12/22 13:15:46
29/12/22 14:30:46
reference:
https://docs.oracle.com/cd/B12037_01/server.101/b10759/functions116.htm
Just do it with the TO_DATE() and TO_CHAR() function pair, both operating on the Oracle date format strings:
Building the scenario:
-- your input ..
WITH indata(dt) AS (
SELECT '10/11/22 12:14:01,807000000' FROM dual UNION ALL
SELECT '11/12/22 13:15:46,650000000' FROM dual UNION ALL
SELECT '29/12/22 14:30:46,501000000' FROM dual
)
-- end of your input. Real query starts here.
-- Change following comma to "WITH" ..
,
-- Now convert to TIMESTAMP(9) ...
as_ts AS (
SELECT
TO_TIMESTAMP(dt ,'DD/MM/YY HH24:MI:SS,FF9') AS ts
FROM indata
)
SELECT
ts
, CAST(ts AS TIMESTAMP(0)) AS recast -- note: this is rounded
, TO_CHAR(ts,'DD/MM/YY HH24:MI:SS') AS reformatted -- this is truncated
FROM as_ts
Result:
TS
RECAST
REFORMATTED
10-NOV-22 12.14.01.807000000
10-NOV-22 12.14.02
10/11/22 12:14:01
11-DEC-22 13.15.46.650000000
11-DEC-22 13.15.47
11/12/22 13:15:46
29-DEC-22 14.30.46.501000000
29-DEC-22 14.30.47
29/12/22 14:30:46
Going by what you have in your question, it appears that the data in the field Date is a timestamp. This isn't a problem, but the names of the table (TABLE) and field (Date) present some challenges.
In Oracle, TABLE is a reserved word - so to use it as the name of a table it must be quoted by putting it inside double-quotes, as "TABLE". Similarly, Date is a mixed-case identifier and must likewise be quoted (e.g. "Date") every time it's used.
Given the above your query becomes:
SELECT TO_CHAR("Date", 'DD/MM/YY HH24:MI:SS') AS FORMATTED_DATE
FROM "TABLE"
and produces the desired results. db<>fiddle here
Generally, it's best in Oracle to avoid using reserved words as identifiers, and to allow the database to convert all names to upper case - if you do that you don't have to quote the names, and you can refer to them by upper or lower case as the database automatically converts all unquoted names to upper case internally.

Alternative for "connect by" Oracle SQL

Anyone be able to give me some script that does the same as the below but not using "connect by"? The code works well, but I cannot use connect by in the BI publisher.
select to_char(to_date('2022-05-01') + (level -1),'YYYY-MM-DD') as read_date
from dual
connect by to_date('2022-05-01') + (level -1) <= to_date('2022-05-05')
CONNECT BY is Oracle's propriatary and concise way to write a recursive query. You can replace it with a standard SQL compliant recursive query that has been supported by Oracle since 2002.
with read_dates(read_date) as
(
select date '2022-05-01' from dual
union all
select read_date + interval '1' day from read_dates
where read_date < date '2022-05-05'
)
select to_char(read_date, 'YYYY-MM-DD')
from read_dates;
Two remarks:
Your own code is vulnarable, because it uses an implicit string to date conversion (to_date('2022-05-01')) that relies on session date settings and can thus fail miserably.
It is rare that we select dates as strings (to_char(..., 'YYYY-MM-DD')), because we usually want our app to know that we are selecting dates.

How to get difference between two rows for a column field? When the column is a timestamp

I found this answer regarding the possibility to get the difference between two rows for a column field ( https://stackoverflow.com/questions/634568/how-to-get-difference-between-two-rows-for-a-column-field#= )
My question is, how can I make the same thing, when the Value is a Timestamp? I am using SQL Server 2012.
The table looks like in the picture below
Basically, what I want to do is to get the difference between two consecutive timestamps to see after how much time, a new DMC went through the process
Hope it's more clear right now. I'm pretty new at this.
Thank you in advance.
Since you are on SQL Server 2012, you can now use LAG/LEAD to get a value of a column from the previous/next row. Then you just calculate the difference as you would between two columns on the same row. Something like this:
create table YOUR_TABLE(ID integer, DT datetime);
insert into YOUR_TABLE
select 2, '02/02/2016 12:00:00' union all
select 3, '02/05/2016 12:00:00' union all
select 4, '02/06/2016 12:00:00' union all
select 5, '02/07/2016 12:00:00'
;
select
ID,
DT,
datediff(day, DT, lead(DT) over (order by ID)) as DIFF
from your_table;

SYSDATE FROM DUAL in another SELECT

I have problems with time in my select. Time in DB is different than system time so I guess I need to use SELECT SYSDATE FROM DUAL but it doesn't work in another select. I use PL/SQL Developer.
SELECT t.something1,
ROUND((TRUNC(SELECT SYSDATE FROM DUAL) - 1 + 2),1) AS NAME
FROM customers t
WHERE t.something1 = ROUND((TRUNC(SELECT SYSDATE FROM DUAL) - 1 + 2),1);
I have also tried to declare new variable but I always get error message.
DECLARE
day DATE
SELECT SYSDATE
INTO day
FROM DUAL
SELECT t.something1,
ROUND((TRUNC(day)- 1 + 2),1) AS NAME
FROM customers t
WHERE t.something1 = ROUND((TRUNC(day) - 1 + 2),1);
You must use SELECT SYSDATE FROM DUAL to get SYSDATE only if you have no table to select from. This is because a SELECT without a FROM is not valid with Oracle, so when you want to use a SQL function and you have no table, you have to use DUAL, which is a special one-row one-column (named DUMMY) table. The only row has the value X.
ROUND(number) function will only work with number data type. It will not work with the date type.
If your t.something1 column data type is date than you can't used round() function (you can directly compare date with date), if it not and is number than you will use round() and you need to convert your sysdate into number and compare.
As per my understanding you do something like below :
SELECT t.something1,
ROUND(to_number(to_char(sysdate+1,'DDMMYYYY')),1) AS NAME
FROM customers t
WHERE t.something1 = ROUND(to_number(to_char(sysdate+1,'DDMMYYYY')),1);
May this will help you.
You don't need the subquery:
SELECT t.something1,
ROUND((TRUNC(SYSDATE) - 1 + 2),1) AS NAME
FROM customers t
WHERE t.something1 = ROUND((TRUNC(SYSDATE) - 1 + 2),1);
Does this fix your problem?

How to select rows by date in sqlite

I have to select all rows from database by just passing date. For example to get all rows that have date 10/23/2012
In sqlite db I store this in DATE column:
01/01/1900 11:00:00 AM
I have tried to get by using date() but I get nothing for date:
select itemId, date(dateColumn) from items
So all I need is to compare only dates but can't find how to do this in sqlite.
Firstly, format your dates to the ISO-8601 standard. Wrap it in Date() to ensure it gets processed as a DATE. Finally, construct your range so that it will include everything from 12:00am onwards until just before 12:00am the next day.
select itemId, dateColumn
from items
where dateColumn >= date('2012-10-23')
AND dateColumn < date('2012-10-23', '+1 day')
SQLite columns are not typed. However, if you compare the column to a DATE as shown, it is sufficient to coerced the column data into dates (null if not coercible) and the comparison will work properly.
Example on SQLFiddle:
create table items (
itemid, datecolumn);
insert into items select
1,'abc' union all select
2,null union all select
3,'10/23/2012 12:23' union all select
4,'10/23/2012' union all select
5,'2012-10-23 12:23' union all select
6,'2012-10-23' union all select
7,'2012-10-24 12:23' union all select
8,'2012-10-24' union all select
9,date('2012-10-24 12:23') union all select
10,date('2012-10-24');
Results:
itemid datecolumn
5 2012-10-23 12:23
6 2012-10-23
Note that although rows 3 and 4 appear to be dates, they are not, because they do not conform to ISO-8601 formatting which is the only format recognized by SQLite.
In SQLite, there is no datatype DATE, it's stored as strings. Therefor, the Strings have to match exactly to be equal.
Since we don't want that, you'll want to "cast" the values from the date-column to pseudo-date and also cast your argument to a pseudo-date, so they can be compared:
SELECT itemId FROM items WHERE date(dateColumn) = date("2012-10-22");
Note that the date-command takes dates formated as YYYY-MM-DD, as further explained in an answer to this older question. The question also shows that you can use the BETWEEN x AND y-command to get dates, matching a range.
SELECT itemId,dateColumn FROM items WHERE dateColumn=date('YYYY-MM-DD HH:MM:SS');
SQLite Reference
select itemId,dateColumn from items
where dateColumn = #date