SELECT MAX keeps converting DATETIME to VARCHAR - sql

Trying to write something that produces the MAX date for a record and then show all records that have a MAX date less than today, but the SQL query keeps converting the DATETIME field to a VARCHAR so I'm unable to use maxdate < GetDate()
The code I'm trying to use is
'Max Day'=(SELECT MAX (del.original_stop) FROM del, line WHERE del.obj_id=T2.obj_id AND del.type=0 AND line.opt <> 1)
T2.obj_id is defined in a LEFT OUTER JOIN in my main FROM clause.
Any ideas?
*Updating w/full query
SELECT
T1.doc AS "Document",
T1.owner AS "Own",
T1.last_up AS "Last Updated (EST)",
"Dollars"=ISNULL((SELECT CAST(SUM(fund_amt) AS DECIMAL(16,2)) FROM c_fund T3 WHERE T2.obj_id=T3.obj_id),0),
"Max Day"=(SELECT MAX(del.orig_stop) FROM del, line WHERE del.obj_id=T2.obj_id AND del.del_type=0 AND line.opt <> 1)
FROM
dsk T1 LEFT OUTER JOIN doc_object T2 ON T1.obj_id=T2.obj_id
WHERE
T1.icon_id=4
AND
T1.last_up >= '2018/01/21' AND T1.last_up <= '2018/01/24'
ORDER BY
"Last Updated (EST)" desc
And I know about the commas in the FROM clause, will fix those shortly.

Use as to assign aliases:
select (SELECT MAX(del.original_stop)
FROM del JOIN
line
ON del.obj_id=T2.obj_id AND del.type=0 AND line.opt <> 1
) as max_day,
. . .
Also, never use commas in the FROM clause. Always use proper, explicit JOIN syntax.
If original_stop is a string, then my first advice is to fix the data. You should be storing dates and times in native formats, not as strings.
If for some reason you cannot fix the data model, then you can use convert() . You'll need to peruse the formats available for the function.

Related

ORA-01722- Invalid Number

I have a query in the package throwing error
ORA-01722 : invalid number.
I tried many ways but no luck.
select h.column
from table1 h,table2 c
where c.created_date='17-MAY-17'
and nvl(c.acct_nmbr,0)=nvl(to_number(h.v_acct_num),0)
c.acct_nmbr is of NUMBER(19,0)
h.v_acct_num is of varchar2(4000 byte)
Please suggest me the solution
If you are using Oracle 12.2 or higher then you can use the TO_NUMBER with ON CONVERSION ERROR clause as follows:
SELECT
H.COLUMN
FROM
TABLE1 H
JOIN TABLE2 C
ON NVL(C.ACCT_NMBR, 0) = NVL(TO_NUMBER(H.V_ACCT_NUM DEFAULT -999 ON CONVERSION ERROR), 0)
-- use any number which is impossible in your column
-- so that it do not match any random records.
WHERE
C.CREATED_DATE = DATE '2017-05-17';
Note:
Use standard ANSI joins
Use DATE literal wherever you want to convert string to date or TO_DATE function
Cheers!!
Obviously v_acct_num column contains non-numeric values. to_number() function has restriction that the value in the argument shouldn't contain any non-numeric character, otherwise the system hurls with ORA-01722 : invalid number. If you're sure about the data matches when non-numeric characters are extracted then use regexp_replace(t2.v_acct_num,'[^[:digit:]]') within the collation of the join's on clause :
select t2.column
from table1 t1
join table2 t2 on nvl(t1.acct_nmbr,0) = nvl(regexp_replace(t2.v_acct_num,'[^[:digit:]]'),0)
where t2.created_date = date'2017-05-17'
Use ANSI-92 standard for Join, and ISO-8601 standard for date syntaxes.
Identify what data is non-numeric:
select * from table1 h
where regexp_like(h.v_acct_num, '[^0-9]')
and delete them
.
Hope it helps.

Exclude '-1.79769313486232E+308' from table using select query in SQL

I want to get the average of the data in one of the table but I get "Arithmetic overflow error converting expression to data type float." exception. My table looks like,
I have to get the average of floating points in the table.
I want to exclude '-1.79769313486232E+308' from the table. How to do that?
Query that I have,
SELECT PS.Name, Z.[Round]
,AVG(Z.[EstimatedValue])
,AVG(Z.[InformationGain])
FROM [dbo].[IntermediateScores] Z
INNER JOIN [dbo].[PScale] PS
ON Z.[ScaleId] = PS.Id
GROUP BY PS.Name, Z.[Round]
ORDER BY PS.Name,Z.[Round]
Assuming that you are running SQL Server (which the syntax of your query and the error message that you showed tend to indicate), you could use TRY_CAST() to handle values that do not fit in the FLOAT datatype. When the conversion fails, TRY_CAST() returns NULL, which aggregate function AVG() ignores.
SELECT
PS.Name,
Z.[Round],
AVG(TRY_CAST(Z.[EstimatedValue] AS FLOAT)),
AVG(TRY_CAST(Z.[InformationGain] AS FLOAT))
FROM [dbo].[IntermediateScores] Z
INNER JOIN [dbo].[PScale] PS ON Z.[ScaleId] = PS.Id
GROUP BY PS.Name, Z.[Round]
ORDER BY PS.Name,Z.[Round]
In general, you want to avoid relying on implicit conversion; it seems like your data is not stored in a numeric datatype, which is the root cause of your problem. Explicit conversion is a better practice, since it is easier to debug when things go wrong.

Query with OR excluding results in SQL

I am performing this query:
SELECT SQL_CALC_FOUND_ROWS uniqueid, start
FROM sometable
LEFT JOIN log ON
sometable.uniqueid = log.anid AND (log.info='someinfo' or log.info='otherinfo')
WHERE `moreInfo` = 1 AND `type` = 'myType'
AND (`channel` LIKE 'ACHANNEL/%' or `channel` LIKE 'OTHERCHANNEL\/%')
AND `start` > '2019-01-22 00:00:00' AND `start` < '2019-01-22 23:59:59'
GROUP BY uniqueid
However this part does not seem to be working:
AND (`channel` LIKE 'ACHANNEL%' or `channel` LIKE 'OTHERCHANNEL%')
I want this to give me all channels that begin with ACHANNEL/, or channel that begins with OTHERCHANNEL/, instead, it always gives me the results that begin with OTHERCHANNEL/.
The OR seems to not be working.
Any help?
Your query should be doing what you want. If you are missing rows then perhaps the patterns don't really match.
I do have some suggestions though:
SELECT SQL_CALC_FOUND_ROWS t.uniqueid, MIN(start) as start
FROM sometable t LEFT JOIN
log l
ON t.uniqueid = l.anid AND l.info in ('someinfo', 'otherinfo')
WHERE t.`moreInfo` = 1 AND
t.`type` = 'myType' AND
(t.`channel` LIKE 'ACHANNEL/%' or t.`channel` LIKE 'OTHERCHANNEL/%') AND
t.`start` > '2019-01-22' AND `start` < '2019-01-23'
GROUP BY t.uniqueid;
Note that I have qualified all column names and assumed that all column references in the WHERE refer to sometable and not log. Otherwise, the LEFT JOIN would be turned into an INNER JOIN.
Notes:
All columns are qualified meaning they use the table aliases. Strongly, strongly recommended when a query has more than one table reference.
The date arithmetic has been simplified.
The multiple comparisons with OR have been simplified using IN.
The "bare" start column has been turned into an aggregation function.
The escape character \ has been removed. There is no need for any escape characters with forward slashes.
You did not escape your first condition:
AND (channel LIKE 'ACHANNEL\/%' or channel LIKE 'OTHERCHANNEL\/%')

Convert Legacy to Standard SQL (Join Each and comma Like)

I'm struggling to convert this Legacy SQL Query to Standard SQL. Particular things that need to be converted are FLATTEN, JOIN EACH, No matching signature for function REGEXP_REPLACE for argument types: ARRAY, STRING, STRING. Supported signatures: REGEXP_REPLACE(STRING, STRING, STRING); REGEXP_REPLACE(BYTES, BYTES, BYTES), etc. ...Can anyone please help?
Thanks!
SELECT a.name, b.name, COUNT(*) as count
FROM (FLATTEN(
SELECT GKGRECORDID, UNIQUE(REGEXP_REPLACE(SPLIT(V2Persons,';'), r',.*'," ")) name
FROM [gdelt-bq:gdeltv2.gkg]
WHERE DATE>20180901000000 and DATE < 20180910000000 and V2Persons like '%Trump%'
,name)) a
JOIN EACH (
SELECT GKGRECORDID, UNIQUE(REGEXP_REPLACE(SPLIT(V2Persons,';'), r',.*'," ")) name
FROM [gdelt-bq:gdeltv2.gkg]
WHERE DATE>20180901000000 and DATE < 20180910000000 and V2Persons like '%Trump%'
) b
ON a.GKGRECORDID=b.GKGRECORDID
WHERE a.name<b.name
GROUP EACH BY 1,2
ORDER BY 3 DESC
LIMIT 250
SELECT a.name, b.b_name, COUNT(*) as count
FROM (
SELECT DISTINCT GKGRECORDID, REGEXP_REPLACE(name, r',.*'," ") name
FROM `gdelt-bq.gdeltv2.gkg`, UNNEST(SPLIT(V2Persons,';')) as name
WHERE DATE>20180901000000 and DATE < 20180910000000 and V2Persons like '%Trump%'
) a
JOIN (
SELECT DISTINCT GKGRECORDID, REGEXP_REPLACE(b_name, r',.*'," ") b_name
FROM `gdelt-bq.gdeltv2.gkg`, UNNEST(SPLIT(V2Persons,';')) as b_name
WHERE DATE>20180901000000 and DATE < 20180910000000 and V2Persons like '%Trump%'
) b
ON a.GKGRECORDID=b.GKGRECORDID
WHERE a.name<b.b_name
GROUP BY 1,2
ORDER BY 3 DESC
LIMIT 250
Re: the flatten I would consult the documentation here: https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql#removing_repetition_with_flatten
Among other examples, the documentation notes:
"Standard SQL does not have a FLATTEN function as in legacy SQL, but you can achieve similar semantics using the JOIN (comma) operator."
Re: Join Each, this has been answered here: BigQuery - equivalent of GROUP EACH in standard SQL
Basically, it is not necessary at all in standard sql
Re: "LIKE that has comma separated parameters...", your syntax is fine for standard sql. it should not operate any differently than it did when you ran in in legacy sql. One of the big pluses of standard sql is that you can compare columns using functions in the WHERE statement with more flexibility than legacy SQL allowed (if necessary). For instance, if you wanted to split V2Persons before running a like comparison, you could do that right in the WHERE statement
UPDATE: Realizing I missed your last question about data type mismatches. In standard sql you will probably want to cast everything explicitly when you run into these errors. It is more finicky than legacy sql with regards to comparisons between different data-types, but I find this to me more in line with other SQL databases.

SQL : Coalesce within where clause giving error Oracle (Not in DB2)

I am trying to use COALESCE in WHERE clause, and I am getting the following error:
ORA-00907: missing right parenthesis Failed SQL stmt:
If I remove the COALESCE, I don't get the error anymore. I am not sure why would it give me this error as the parenthesis seem correct. Here's my SQL statement:
SELECT S.OPRID, A.OPRNAME, S.EMAIL_ADDR
FROM TABLE1 S, TABLE2 A
WHERE COALESCE(S.REHIRE_DT,S.ORIG_HIRE_DT)
BETWEEN (TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM- DD'),'YYYY-MM-DD') - 3 DAY)
AND (TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-DD'),'YYYY-MM-DD') - 1 DAY)
AND S.EMPLSTATUS = 'A'
AND A.EMPLID = S.EMPLID
ORDER BY S.OPRID
Take the "DAY" word out. That is not used in oracle in that manner:
SELECT S.OPRID, A.OPRNAME, S.EMAIL_ADDR
FROM TABLE1 S, TABLE2 A
WHERE COALESCE(S.REHIRE_DT,S.ORIG_HIRE_DT)
BETWEEN (TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM- DD'),'YYYY-MM-DD') - 3 )
AND (TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-DD'),'YYYY-MM-DD') - 1 )
AND S.EMPLSTATUS = 'A'
AND A.EMPLID = S.EMPLID
ORDER BY S.OPRID
"DAY" is a keyword to be used as part of the EXTRACT function - see Here
The default unit of subtraction from a date field is already in units of days. I am not familiar with DB2, but I am assuming that your usage of DAY is a DB2-specific attribute. That is probably not portable SQL. Yes, oracle's error messages can be confusing at times.
Now that I think about it, you can replace all that "TO_DATE" stuff with just:
BETWEEN TRUNC(SYSDATE)-3 AND TRUNC(SYSDATE)-1