case statement in window functions - sql

I'm trying to put indicators to each unique bundle (subs_key, ban_key) in each of the two months
I get null values everywhere (i.e. case statement does not work)
Can you help me what to find the error?
select
s.subs_key ||s.ban_key,
s.TIME_KEY,
s.PRICE_PLAN_CHANGE_DATE,
s. active_group,
(case
when s.time_key = to_date('01.05.21','dd.mm.yy') and s. active_group = '1' and s.time_key = to_date ('01.06.21', 'dd.mm.yy') and s. active_group = '0' then 'out paid migr'
when s.time_key = to_date('01.05.21','dd.mm.yy') and s. active_group = '0' and s.time_key =to_date ('01.06.21', 'dd.mm.yy') and s. active_group = '1' then 'in paid migr'
when s.time_key = to_date('01.05.21','dd.mm.yy') and s. active_group = '1' and s.time_key =to_date ('01.06.21', 'dd.mm.yy') and s. active_group = '1' then 'core base'
end as migration_status) over (partition by s.subs_key ||s.ban_key order by s.time_key )

First, your case expression has an over clause. That is incorrect syntax. You need an appropriate analytic function.
Second, use a date constant. Assuming the time key has not components.
Third, a time_key cannot have two values at the same time, yet you are comparing the time_key to two values.
It is unclear what you want to do, because you have not provided sample data, desired results, or an explanation of what the code should be doing. However, the code you have in the question is syntactically and logically incorrect, so it should only produce an error.

Related

Issue With SQL Pivot Function

I have a SQL query where I am trying to replace null results with zero. My code is producing an error
[1]: ORA-00923: FROM keyword not found where expected
I am using an Oracle Database.
Select service_sub_type_descr,
nvl('Single-occupancy',0) as 'Single-occupancy',
nvl('Multi-occupancy',0) as 'Multi-occupancy'
From
(select s.service_sub_type_descr as service_sub_type_descr, ch.claim_id,nvl(ci.item_paid_amt,0) as item_paid_amt
from table_1 ch, table_" ci, table_3 s, table_4 ppd
where ch.claim_id = ci.claim_id and ci.service_type_id = s.service_type_id
and ci.service_sub_type_id = s.service_sub_type_id and ch.policy_no = ppd.policy_no)
Pivot (
count(distinct claim_id), sum(item_paid_amt) as paid_amount For service_sub_type_descr IN ('Single-occupancy', 'Multi-occupancy')
)
This expression:
nvl('Single-occupancy',0) as 'Single-occupancy',
is using an Oracle bespoke function to say: If the value of the string Single-occupancy' is not null then return the number 0.
That logic doesn't really make sense. The string value is never null. And, the return value is sometimes a string and sometimes a number. This should generate a type-conversion error, because the first value cannot be converted to a number.
I think you intend:
coalesce("Single-occupancy", 0) as "Single-occupancy",
The double quotes are used to quote identifiers, so this refers to the column called Single-occupancy.
All that said, fix your data model. Don't have identifiers that need to be quoted. You might not have control in the source data but you definitely have control within your query:
coalesce("Single-occupancy", 0) as Single_occupancy,
EDIT:
Just write the query using conditional aggregation and proper JOINs:
select s.service_sub_type_descr, ch.claim_id,
sum(case when service_sub_type_descr = 'Single-occupancy' then item_paid_amt else 0 end) as single_occupancy,
sum(case when service_sub_type_descr = 'Multi-occupancy' then item_paid_amt else 0 end) as multi_occupancy
from table_1 ch join
table_" ci
on ch.claim_id = ci.claim_id join
table_3 s
on ci.service_type_id = s.service_type_id join
table_4 ppd
on ch.policy_no = ppd.policy_no
group by s.service_sub_type_descr, ch.claim_id;
Much simpler in my opinion.
for column aliases, you have to use double quotes !
don't use
as 'Single-occupancy'
but :
as "Single-occupancy",

Redshift Correlated Subquery Internal Error

So I have a table of bids in Amazon Redshift. Each bid has a description and a user who made the bid, and for each bid I want to know if a user made a bid with the same description in the last 5 days.
The query looks like this:
select b1.bid_id, case when
exists(select b2.bid_id from dim_bid b2 WHERE b1.user_id = b2.user_id
and b2.bid_timestamp < b1.bid_timestamp and b2.bid_timestamp > b1.bid_timestamp - INTERVAL '5 day'
and b2.description = b1.description and b2.bid_timestamp > '2017-04-25') then 'good bid' else 'duplicate bid' END
from dim_bid b1
where b1.hidden
which doesn't work, giving the error: this type of correlated subquery is not supported due to internal error. However when I just add a "=True" at the end it works.
select b1.bid_id, case when
exists(select b2.bid_id from dim_bid b2 WHERE b1.user_id = b2.user_id
and b2.bid_timestamp < b1.bid_timestamp and b2.bid_timestamp > b1.bid_timestamp - INTERVAL '5 day'
and b2.description = b1.description and b2.bid_timestamp > '2017-04-25') then 'good bid' else 'duplicate bid' END
from dim_bid b1
where b1.hidden = True
Is this just a bug, or is there some deep reason why the first one can't be done?
I think the better way to write the query uses lag():
select b.*,
(case when lag(b.bid_timestamp) over (partition by b.description order by b.timestamp) > b.bid_timestamp - interval '5 day'
then 'good bid' else 'duplicate bid'
end)
from dim_bid b;
Try to run this first:
select b1.bid_id
from dim_bid b1
where b1.hidden
You will see that redshift will raise a different error(eg. WHERE must be type boolean...). So argument of where must be a boolean in order for the query to run. So when you add '=True' then argument is boolean and query runs. And when the query has correlated subquery and there is an invalid operation in the query I have noticed that redshift raises correlated subquery error. This might be due to the fact that redshift does not support some of the correlated subqueries(correlated subqueries redshift).
The docs state the following:
We recommend always checking Boolean values explicitly, as shown in the examples following. Implicit comparisons, such as WHERE flag or WHERE NOT flag might return unexpected results.
Reference: http://docs.aws.amazon.com/redshift/latest/dg/r_Boolean_type.html
I do not think this is necessarily a bug. I would recommend always checking boolean values as where b1.hidden is True. I have seen this error quite a few times when using correlated subqueries, but I have always been able to fix it when explicitly checking the boolean values using is true/false/unknown.

SQL Subquery to replace all values

I have a query which returns a bunch of different data, however I want to have it replace all the values upon a certain condition.
What I have written below kind of gives me the result I want but not really. It creates a new column instead of replacing the other one:
SELECT
CASE
WHEN T4.[U_DestType] = '6'
THEN (SELECT
'Company Limited' AS [ShipToCode]
)
END AS [ShipToCode],
T2.[ShipToCode],
T6.[StreetS],
T6.[StreetNoS],
T6.[CityS],
T6.[ZipCodeS],
T6.[CountryS],
T5.[LicTradNum],
T2.[CardCode],
T4.[Phone1],
T4.[E_Mail],
T4.[U_DestType],
CASE
WHEN T4.[Country] = 'GB'
THEN 'EN'
ELSE T4.[Country]
END AS [Country],
T4.[U_ShortName]
FROM[...]
The end goal is to replace all of the columns with some preset values instead of just ShipToCode as above.
I tried putting an EXIST subquery after FROM too but that didn't work either.
Is this possible? I'm probably missing something very obvious.
Many thanks!
You can use an ELSE in your CASE expression to combine the two "columns":
CASE
WHEN T4.[U_DestType] = '6'
THEN (SELECT
'Company Limited' AS [ShipToCode]
)
ELSE T2.[ShipToCode]
END AS [ShipToCode],
And by the way, you didn't need to use a Sub-Select. This would work just as well and is easier to read:
CASE
WHEN T4.[U_DestType] = '6' THEN 'Company Limited'
ELSE T2.[ShipToCode]
END AS [ShipToCode],

Error: Error converting data type varchar to numeric, using Hashbytes function in SQL

I have a legacy SSIS package that needs updating. Specifically it used to only add new records and must now update and end date or delete records as appropriate. elsewhere in the package I've been using the Hashbytes function with great success to evaluate which rows need to be updated by taking matching datasets from both databases and then comparing them as part of a conditional split. The problem I'm having revolves around a case statement in the source query:
SELECT DISTINCT
DTBL_STUDENTS.STUDENT_ID,
FTBL_TEST_SCORES.TEST_STUDENT_GRADE,
DTBL_TESTS.TEST_NAME,
DTBL_SCHOOL_DATES.DATE_VALUE AS Assessment_Date,
DTBL_SCHOOL_DATES.SIS_SCHOOL_YEAR AS Assessment_Year,
left( CASE
WHEN FTBL_TEST_SCORES.TEST_SCORE_TEXT = 'NA'
THEN CASE
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'INTE' THEN 'High'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'STRA' THEN 'Some'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'BNCH' THEN 'Low'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT IN ('High', 'Some', 'Low') THEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT
ELSE FTBL_TEST_SCORES.TEST_SCORE_TEXT
END
ELSE CASE
WHEN FTBL_TEST_SCORES.TEST_SCORE_TEXT LIKE '%.0000'
THEN REPLACE(FTBL_TEST_SCORES.TEST_SCORE_TEXT, '.0000', '')
ELSE FTBL_TEST_SCORES.TEST_SCORE_TEXT
END
END,12) AS TEST_SCORE_TEXT,
CASE
WHEN FTBL_TEST_SCORES.TEST_SCORE_TEXT = 'NA'
THEN CASE
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'INTE' THEN '1'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'STRA' THEN '3'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT_CODE = 'BNCH' THEN '4'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT = 'High' THEN '1'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT = 'Some' THEN '3'
WHEN FTBL_TEST_SCORES.TEST_PRIMARY_RESULT = 'Low' THEN '4'
ELSE '0'
END
ELSE FTBL_TEST_SCORES.TEST_SCORE_VALUE
END AS TEST_SCORE_VALUE,
FTBL_TEST_SCORES.TEST_PERCENTILE_SCORE,
DTBL_SCHOOLS.SCHOOL_HR_ID
FROM K12INTEL_DW.DTBL_TESTS
JOIN K12INTEL_DW.FTBL_TEST_SCORES ON FTBL_TEST_SCORES.TESTS_KEY =
DTBL_TESTS.TESTS_KEY
JOIN K12INTEL_DW.DTBL_SCHOOL_DATES ON DTBL_SCHOOL_DATES.SCHOOL_DATES_KEY =
FTBL_TEST_SCORES.SCHOOL_DATES_KEY
JOIN K12INTEL_DW.DTBL_STUDENTS ON DTBL_STUDENTS.STUDENT_KEY =
FTBL_TEST_SCORES.STUDENT_KEY
JOIN K12INTEL_DW.DTBL_SCHOOLS ON DTBL_SCHOOLS.SCHOOL_KEY =
FTBL_TEST_SCORES.SCHOOL_KEY
WHERE DTBL_SCHOOL_DATES.SIS_SCHOOL_YEAR = 2014
AND DTBL_STUDENTS.STUDENT_CURRENT_DISTRICT_CODE = '2180'
AND FTBL_TEST_SCORES.TEST_STUDENT_GRADE IN ('PS', 'PK', 'KG', '01', '02',
'03', '04', '05', '06', '07', '08')
AND DTBL_TESTS.TEST_VENDOR IS NOT NULL
AND FTBL_TEST_SCORES.TEST_HIGHEST_SCORE_INDICATOR IN ('Yes', '--')
The 3 values I need to hash for comparison are:
TEST_SCORE_TEXT
TEST_SCORE_VALUE
Assessment_Date
It looks like it's choking on TEST_SCORE_VALUE in the function:
HASHBYTES('SHA1',ISNULL(#Dware.TEST_SCORE_TEXT,'')+convert(varchar(10),ISNULL(TEST_SCORE_VALUE,''))+convert(varchar(50),(ISNULL(Assessment_Date,'')))) as SourceHash
This is where I get the error "Error converting data type varchar to numeric". I've tried putting my source query into a subquery and doing a select*, (function) from that source query. I've tried putting the case statement into the hashbytes function, and I've tried using a temp table. My assumption is that it's getting the underlying value rather than the value generated by the case statement but I don't know why,or how to fix it so that I get the numeric values I'm expecting/wanting.
Many thanks for any assistance!
Assuming FTBL_TEST_SCORES.TEST_SCORE_VALUE is numeric, then look at your CASE statement that creates TEST_SCORE_VALUE. You create a string by evaluating TEST_PRIMARY_RESULT_CODE and TEST_PRIMARY_RESULT, etc, but your final ELSE statement is probably returning a numeric value (FTBL_TEST_SCORES.TEST_SCORE_VALUE).
I believe Sql Server determines the output type of the CASE statement by the last return value. (In any case, itt has an algorithm for determining the return type when individual THEN statements are mixed.)
So, it sees your CASE statement as typed to whatever FTBL_TEST_SCORES.TEST_SCORE_VALUE is, which is probably inconsistent with the earlier varchar return values of the CASE statement.
Fix that, and the HASHBYTES function should work, as is.
+convert(varchar(10),ISNULL(TEST_SCORE_VALUE,''))
Turns out that should've been:
+convert(varchar(10),ISNULL(TEST_SCORE_VALUE,0))
and then it all worked fine.

Use Case Statement in Join

Hi every one i want to use case statement in join using this query and got error
Select CONVERT(VARCHAR(10), SII.SIDATE,103)DATE,SII.SALEID,SII.ItemName,SI.TenancyID
FROM F_SALESINVOICEITEM SII
INNER JOIN F_SALESINVOICE SI ON SI.SALEID=SII.SALEID
INNER JOIN #TempTableSearch ts ON CASE
WHEN ts.ACCOUNTTYPE = '1' THEN ts.ACCOUNTID=SI.TENANCYID
WHEN ts.ACCOUNTTYPE='2' THEN ts.ACCOUNTID=SI.EMPLOYEEID
WHEN ts.ACCOUNTTYPE='3' THEN ts.ACCOUNTID=SI.SUPPLIERID
WHEN ts.ACCOUNTTYPE='4' THEN ts.ACCOUNTID=SI.SALESCUSTOMERID
Error
Incorrect syntax near '='.
Please help me to solve this error.
IT should be,
ON
ts.ACCOUNTID = CASE
WHEN ts.ACCOUNTTYPE = '1' THEN SI.TENANCYID
WHEN ts.ACCOUNTTYPE = '2' THEN SI.EMPLOYEEID
WHEN ts.ACCOUNTTYPE = '3' THEN SI.SUPPLIERID
WHEN ts.ACCOUNTTYPE = '4' THEN SI.SALESCUSTOMERID
END
Instead of using CASE, I'd much rather do this:
Select CONVERT(VARCHAR(10), SII.SIDATE,103)DATE,SII.SALEID,SII.ItemName,SI.TenancyID
FROM F_SALESINVOICEITEM SII
INNER JOIN F_SALESINVOICE SI ON SI.SALEID=SII.SALEID
INNER JOIN #TempTableSearch ts ON
(ts.ACCOUNTTYPE='1' AND ts.ACCOUNTID=SI.TENANCYID)
OR (ts.ACCOUNTTYPE='2' AND ts.ACCOUNTID=SI.EMPLOYEEID)
OR (ts.ACCOUNTTYPE='3' AND ts.ACCOUNTID=SI.SUPPLIERID)
OR (ts.ACCOUNTTYPE='4' AND ts.ACCOUNTID=SI.SALESCUSTOMERID)
To explain why the query didn't work for you: the syntax of the CASE requires an END at the end of the clause. It would work, as the other solutions proposed suggest, but I find this version to be more convenient to understand - although this part is highly subjective.
you can do this, so you have no chance to misspell something (note that ACCOUNTTYPE and ACCOUNTID used only when needed, you don't have to copy-paste it)
select
convert(varchar(10), SII.SIDATE,103) as DATE,
SII.SALEID, SII.ItemName, SI.TenancyID
from F_SALESINVOICEITEM as SII
inner join F_SALESINVOICE as SI on SI.SALEID = SII.SALEID
outer apply (
'1', SI.TENANCYID
'2', SI.EMPLOYEEID
'3', SI.SUPPLIERID
'4', SI.SALESCUSTOMERID
) as C(ACCOUNTTYPE, ACCOUNTID)
inner join #TempTableSearch as ts on
ts.ACCOUNTTYPE = C.ACCOUNTTYPE and ts.ACCOUNTID = C.ACCOUNTID
You have syntax error. You are missing END there.
You must understand that CASE ... END block is NOT equivalent to IF { } from C-like languages. Much rather this is equivalent to elaborate version of ... ? ... : ... operator from C-like languages. What it means that the WHOLE CASE block must essentially evaluate to single value and that this value has to be the same type no matter which case of the block is executed. This means that:
CASE
WHEN ts.ACCOUNTTYPE = '1' THEN ts.ACCOUNTID=SI.TENANCYID ...
END
Is fundamentally incorrect unless you work on a version of database that will allow you bool value as a value (SQL Server won't allow it for example but I think some of MySQL version used to allow it - not sure about this). You probably should write something like:
CASE
WHEN ts.ACCOUNTTYPE = '1' AND ts.ACCOUNTID=SI.TENANCYID THEN 1
WHEN ts.ACCOUNTTYPE='2' AND ts.ACCOUNTID=SI.EMPLOYEEID THEN 1
WHEN ts.ACCOUNTTYPE='3' AND ts.ACCOUNTID=SI.SUPPLIERID THEN 1
WHEN ts.ACCOUNTTYPE='4' AND ts.ACCOUNTID=SI.SALESCUSTOMERID THEN 1
ELSE 0
END = 1
Notice how the whole CASE block evaluates to 1 or 0 and then it is compared to 1. Of course instead of 4 WHEN's you could use one WHEN with combination of AND's, OR's and ( ) brackets. Of course in this particular case answer by #ppeterka 66 is correct as CASE is not suited for what you really wanted to do - I'm just trying to clarify what CASE really is.