Missing expression error when creating a view - sql

I have the following oracle query to create a view :
CREATE VIEW uvw_Dashboard_Templates
AS
SELECT LL.ID
,LL.LoadDate
,LL.FileName
,LL.TemplateType
,LL.AnalystName
,LL.RecDate
,LL.CompanyID
,LL.CompanyName
,LL.Recommendation
,LL.Loaded
,LL.ErrorText
,CASE
WHEN LL.NewCompany = 1 AND LL.Loaded = 0 THEN 0
ELSE LL.NewCompany END NewCompany
,RH.rec_date LastRecDate
,RH.rec_code LastRecCode
,CONVERT(NUMBER(1), CASE
WHEN LL.Loaded = 1 AND NVL(LL.Recommendation, 'Rec') <>
NVL(RH.rec_code,'LastRec') THEN 1
ELSE 0 END) RecChanged
FROM tblTemplates_LoadLog LL
LEFT JOIN (
SELECT company_id, rec_date, rec_code
FROM (
SELECT company_id
, rec_date
, UPPER(rec_code) rec_code
, ROW_NUMBER() OVER(PARTITION BY company_id ORDER BY rec_date DESC) RowNumber
FROM tblRecHist
) OrderedList
WHERE RowNumber = 2) RH
ON LL.CompanyID = RH.company_id
which is throwing a
ORA-00936: missing expression error on running.
What is the possible cause of this?

change this:
,CONVERT('1', CASE
The Oracle/PLSQL CONVERT function converts a string from one character set to another.
CONVERT( string1, char_set_to [, char_set_from] )
you gotta give in string there

It looks like you're trying to use the SQL Server convert() function. Oracle does have its own convert() function, but it's not related at all:
CONVERT converts a character string from one character set to another.
The closest equivalent I can see to the SQL Server function would be to cast it:
,CAST(CASE
WHEN LL.Loaded = 1 AND NVL(LL.Recommendation, 'Rec') <>
NVL(RH.rec_code,'LastRec') THEN 1
ELSE 0 END AS NUMBER(1)) RecChanged
Describing the view would show the column as NUMBER(1), which I assume is the point of converting/casting it in the first place, since you know it conforms to the scale/precision constraint already.

Related

Impala SQL Query

Error Message :
select list expression not produced by aggregation output (missing
from GROUP BY clause?): CASE WHEN (flag = 1) THEN date_add(lead_ctxdt,
-1) ELSE ctx_date END lot_endt
code :
select c.enrolid, c.ctx_date, c.ctx_regimen, c.lead_ctx, c.lead_ctxdt, min(c.ctx_date) as lot_stdt,
case when (flag = 1 ) then date_add(lead_ctxdt, -1)
else ctx_date
end as lot_endt
from
(
select p.*,
case when (ctx_regimen <> lead_ctx) then 1
else 0
end as flag
from
(
select a.*, lead(a.ctx_regimen, 1) over(partition by enrolid order by ctx_date) as lead_ctx,
lead(ctx_date, 1) over (partition by enrolid order by ctx_date) as lead_ctxdt
from
(
select enrolid, ctx_date, group_concat(distinct ctx_codes) as ctx_regimen
from lotinfo
where ctx_date between ctx_date and date_add(ctx_date, 5)
group by enrolid, ctx_date
) as a
) as p
) as c
group by c.enrolid, c.ctx_date, c.ctx_regimen, c.lead_ctx, c.lead_ctxdt
I want to get the lead_ctx date minus one as the date when the flag is 1
So i found the answer by executing a couple of times the minor changes. Let me tell you, that when you are trying to min or max alongside you have group_conact in the same query then in Impala this doesn't work. You have to write it in two queries per one more sub query and the min() of something in the outer query or vice versa.
Thank you #dnoeth for letting me understand I have the answer with me already.

Query won't convert a nvarchar(30) to a decimal

I have the following query, that when it is run gives the following error:
Conversion failed when converting the nvarchar value '247.300' to data type int.
The query is as follows:
SELECT UD.SerialNumber,
UD.ReadingDate,
UD.ChannelName,
CONVERT(decimal(18,2), ChannelValue) - LAG(CONVERT(decimal(18,2), ChannelValue),1,
CONVERT(decimal(18,2), ChannelValue)) OVER (PARTITION BY ChannelName,
CASE ChannelValue WHEN 0 THEN 0 ELSE 1 END ORDER BY ReadingDate ASC)
FROM [Staging].[UriData] UD
WHERE UD.ChannelName IN (SELECT ChannelName FROM [Staging].[ActiveChannels])
ORDER BY ReadingDate;
Here is a fiddle: DB Fiddle
The only difference between the fiddle (which works fine) and the query here is that I have to have the ChannelValue column NVARCHAR as some of the data will be in text. I have filtered out all of the text data in the query.
I have also tested it with the following query and the data doesn't show up. If it wasn't a number I would expect it to appear here.
select ChannelValue
from [Staging].[UriData]
where try_convert(numeric(18, 2), ChannelValue) is null and ChannelValue is not null;
The expected outcome is that the number '247.300' is converted into a number and processed. Why won't it convert?
If you read the error message it complains about int.
this is from the implicit cast here
CASE ChannelValue WHEN 0 THEN 0 ELSE 1 END
Use an explicit cast
CASE CONVERT(decimal(19,3), ChannelValue) WHEN 0 THEN 0 ELSE 1 END
then values such as 247.300 will convert fine and be comparable to the integer 0.
Though you also say "I have filtered out all of the text data in the query.". In that case you should always use TRY_CONVERT anyway in case operations get ordered such that the conversion happens before the filter.
You cannot easily filter out text values in SQL Server -- the database reserves the right to re-arrange operations and this might cause an error.
So, use TRY_CONVERT():
SELECT UD.SerialNumber,
UD.ReadingDate,
UD.ChannelName,
(TRY_CONVERT(decimal(18, 2), ChannelValue) -
TRY_CONVERT(DECIMAL(18, 2), LAG(ChannelValue), 1, ChannelValue) OVER (PARTITION BY ChannelName, CASE ChannelValue WHEN '0' THEN 0 ELSE 1 END ORDER BY ReadingDate ASC))
)
FROM [Staging].[UriData] UD
WHERE UD.ChannelName IN (SELECT ChannelName
FROM [Staging].[ActiveChannels]
)
ORDER BY ReadingDate;
If ChannelValue is a string, then the comparison in the CASE should be to a string value.
Under most circumstances, you would only need to do the conversion once. However, to avoid a problem with the subtraction, you also have to convert before the subtraction.
You can use this logic to simplify:
SELECT UD.SerialNumber,
UD.ReadingDate,
UD.ChannelName,
(ChannelValue_d -
LAG(ChannelValue_d), 1, ChannelValue_d) OVER (PARTITION BY ChannelName, CASE ChannelValue WHEN '0' THEN 0 ELSE 1 END ORDER BY ReadingDate ASC)
)
FROM [Staging].[UriData] UD CROSS APPLY
(VALUES (TRY_CONVERT(decimal(18, 2), ChannelValue) )
) v(ChannelValue_d)
WHERE UD.ChannelName IN (SELECT ChannelName
FROM [Staging].[ActiveChannels]
)
ORDER BY ReadingDate;

Why this sql will cause type conversion error?

WITH tb_testl AS (
SELECT 1 AS id ,'hehe' AS value
UNION ALL
SELECT 1 AS id, '1' AS value
UNION ALL
SELECT 2 AS id, '2' AS value
UNION ALL
SELECT 2 AS id, '2' AS value
), tb_test2 AS (
SELECT CONVERT(INT , value) AS value FROM tb_testl WHERE id = 2
)
SELECT * FROM tb_test2 WHERE value = 2;
this sql will cause error
Conversion failed when converting the varchar value 'hehe' to data
type int.
but the table tb_test2 dosen't have the value 'hehe' which is in the anthor table tb_test1. And I found that this sql will work well if I don't append the statement WHERE value = 2; .I've tried ISNUMBERIC function but it didn't work.
version:mssql2008 R2
With respect to the why this occurs:
There is a Logical Processing Order, which describes the order in which clauses are evaluated. The order is:
FROM
ON
JOIN
WHERE
GROUP BY
WITH CUBE or WITH ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP
You can also see the processing order when you SET SHOWPLAN_ALL ON. For this query, the processing is as follows:
Constant scan - this is the FROM clause, which consists of hard coded values, hence the constants.
Filter - this is the WHERE clause. While it looks like there are two where clauses (WHERE id = 2 and WHERE value = 2). SQL Server sees this differently, it considers a single WHERE clause: WHERE CONVERT(INT , value) = 2 AND id = 2.
Compute scaler. This is the CONVERT function in the select.
Because both WHERE clauses are executed simultaneously, the hehe value is not filtered out of the CONVERT scope.
Effectively, the query is simplified to something like:
SELECT CONVERT(INT, tb_testl.value) AS Cvalue
FROM (
SELECT 1 AS id
, 'hehe' AS value
UNION ALL
SELECT 1 AS id
, '1' AS value
UNION ALL
SELECT 2 AS id
, '2' AS value
UNION ALL
SELECT 2 AS id
, '2' AS value
) tb_testl
WHERE CONVERT(INT, tb_testl.value) = 2
AND tb_testl.id = 2
Which should clarify why the error occurs.
With SQL, you cannot read code in the same way as imperative languages like C. Lines of SQL code are not necessarily (mostly not at all, in fact) executed in the same order it is written in. In this case, it's an error to think the inner where is executed before the outer where.
SQL Server does not guarantee the order of processing of statements (with one exception below). That is, there is no guarantee that WHERE filtering happens before the SELECT. Or that one CTE is evaluated before another. This is considered an advantage because it allows SQL Server to rearrange the processing to optimize performance (although I consider the issue that you are seeing a bug).
Obviously, the problem is in this part of the code:
tb_test2 AS (
SELECT CONVERT(INT, value) AS value
FROM tb_testl
WHERE id = 2
)
(Well, actually, it is where tb_test2 is referenced.)
What is happening is that SQL Server pushes the CONVERT() to where the values are being read, so the conversion is attempted before the WHERE clause is processed. Hence, the error.
In SQL Server 2012+, you can easily solve this using TRY_CNVERT():
tb_test2 AS (
SELECT TRY_CONVERT(INT, value) AS value
FROM tb_testl
WHERE id = 2
)
However, that doesn't work in SQL Server 2008. You can use the fact that CASE does have some guarantees on the order of processing:
tb_test2 AS (
SELECT (CASE WHEN value NOT LIKE '%[^0-9]%' THEN CONVERT(INT, value)
END) AS value
FROM tb_testl
WHERE id = 2
)
error caused by this part of statement
), tb_test2 AS (
SELECT CONVERT(INT , value) AS value FROM tb_testl WHERE id = 2
value has type of varchar and 'hehe' value cannot be converted to integer
WITH tb_testl AS (
SELECT 1 AS id ,'hehe' AS value
UPDATE: sql try convert all value(s) to integer in you statement. to avoid error rewrite statement as
WITH tb_testl AS (
SELECT 1 AS id ,'hehe' AS value
UNION ALL SELECT 1 AS id, '1' AS value
UNION ALL SELECT 2 AS id, '2' AS value
UNION ALL SELECT 2 AS id, '2' AS value
), tb_test2 AS (
SELECT value AS value FROM tb_testl WHERE id = 2
),
tb_test3 AS (
SELECT cast(value as int) AS value FROM tb_test2
)
SELECT * FROM tb_test3

SQL LEFT() not working as expected when used with GROUP BY and Partition

I have codes that are like 1231231A, 1231231A, 3453454B etc
I need to group them by their number (ignoring the char which is a version) and just get one of each. I also need to drop the last char. My code works in grouping them and returning one of each, but it returns the last char.
Why is it returning the last char when i chop it off?
Expected output is
1231231
3453454
What I'm getting is
1231231A
3453454B
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER(PARTITION BY T.fldProductDescrip
ORDER BY T.fldEffectiveDate DESC) AS rn
FROM (
-- Insert statements for procedure here
SELECT JST.flduid
,JST.fldEffectiveDate
,(CASE
WHEN RIGHT(fldProductDescrip, 1) LIKE '[0-9]'
THEN fldProductDescrip
ELSE LEFT(fldProductDescrip, DATALENGTH(fldProductDescrip) - 1)
END) as fldProductDescrip
,(
CASE
WHEN PE.fldLogoutDateTime IS NULL
THEN PE.fldESigUser
ELSE ''
END
) AS LoggedIn
,(
CASE
WHEN PE.fldLogoutDateTime IS NULL
THEN PE.fldLoginDateTime
ELSE ''
END
) AS LoggedInDateTime
FROM tblJSJobSheetTemplates JST
INNER JOIN tblJSProducts JP ON JST.fldProductUID = JP.fldUID
INNER JOIN tblJSProductEsig PE ON JP.fldProductDescrip = PE.fldProduct
) AS T
WHERE LoggedIn <> ''
)AS G WHERE rn = 1

ORA-00905: missing keyword error in case after where clause

I have the following query which is giving error ORA-00905: missing keyword. I've not been able to find the syntax despite continuous efforts for last few hours. Please help.
SELECT a.DOCUMENT_CATEGORY,
a.template_id,
a.category_id,
a.REVIEW_CATEGORY,
a.WITH_BIDS,
a.WITH_FINAL_DOCUMENTS,
b.divn_id,
b.deptt_id,
a.vdr_id,
C.DEPARTMENT,
a.TEMPLATE_TITLE
FROM DCTM_VDR_REF_DTLS a, DCTM_VDR_REF_MASTER b, VW_DIVN_DIR c
WHERE b.DIVN_ID = c.DIVN_CODE
AND b.DEPTT_ID = c.SECTN_CODE
AND a.vdr_id = b.vdr_id
AND (b.REFERENCE_NUMBER, b.APPROVED_ON) IN
( SELECT MAX (REFERENCE_NUMBER), MAX (APPROVED_ON)
FROM DCTM_VDR_REF_MASTER
WHERE REFERENCE_NUMBER =
(SELECT DISTINCT
NVL (TRIM (MR_NUMBER), TRIM (TENDER_NO))
FROM EILEDMS.EIL_DOCUMENT_SV#EDMS_DBLINK
WHERE object_name =
'A307-0IC-JA-MR-7960-1030-157-FOA'
AND r_object_type =
'eil_foa_order_pr_doc'
AND ( title = 'FOA'
OR title = 'DRAFT FOA'))
AND APPROVED_ON IS NOT NULL
GROUP BY DIVN_ID, DEPTT_ID)
AND REVIEW_CATEGORY <> 'Delete Category'
AND (CASE (SELECT IS_SCHEDULE_LOCKED
FROM DCTM_VENDOR_SCHEDULE
WHERE SCH_ID = 359)
WHEN 0
THEN
1
WHEN 1
THEN
(a.template_id || '-' || a.category_id) IN
(SELECT template_id || '-' || category_id
FROM DCTM_VENDOR_SCH_UNLOCK_DTLS
WHERE APPROVAL = 'Y'
AND APPROVAL_UPTO >= SYSDATE
AND CONSUMED = 0
AND sch_ID = 359)
END) = 1
ORDER BY c.DEPARTMENT ASC,
a.TEMPLATE_ID,
a.SORT_ORDER,
a.DOCUMENT_CATEGORY ASC
Can't we use IN clause inside a THEN statement?
Now that you've edited your question, it looks like you are simply trying to look up category_id and template_id in DCTM_VENDOR_SCH_UNLOCK_DTLS. Does the following work for you?
then
(
SELECT COUNT(*) -- 1 if found, 0 otherwise
FROM DCTM_VENDOR_SCH_UNLOCK_DTLS
WHERE APPROVAL = 'Y'
AND APPROVAL_UPTO >= SYSDATE
AND CONSUMED = 0
AND sch_ID = 359
AND template_id = a.template_id
AND category_id = a.category_id
AND rownum = 1
)
This is not actually about an IN clause after WHERE being allowed or not. The expression
a.category_id IN (SELECT ...)
evaluates to TRUE or FALSE. Your statement
a.template_id || '-' || a.category_id IN (SELECT ...)
tries to concatenate that TRUE or FALSE with a.template_id and a minus sign. This is not possible, as there is no boolean type in Oracle SQL. Think it over what you actually want to concatenate.
EDIT: Now that you set parentheses, you compare a string with another string resulting from a select statement. Fine so far. But still: All this evaluates to a boolean, not a number. Your first then results in a number (1), your second in a boolean (TRUE or FALSE). Oracle SQL has no boolean type, so your expression makes no sense to the parser and you get a syntax error.