How do I use conditions properly in PSQL? - sql

I wanted to do a condition wherein I put values (000000) in DATE_COMPLETED if it see's the FLAG_CLOSED = Y and if its not Y then do nothing
SELECT
"JOB",
"SUFFIX",
"SUFFIX",
"DATE_COMPLETED",
"FLAG_CLOSED",
CASE "DATE_COMPLETED"
WHEN "FLAG_CLOSED"='Y'
THEN "DATE_COMPLETED"='000000'
END "DATE_COMPLETED"
FROM "JOB_OPERATIONS"
What I got
SQL Execution Error
[LNA][PSQL][SQL Engine]Syntax Error: SELECT
"JOB",
"SUFFIX",
"SUFFIX",
"DATE_COMPLETED",
"FLAG_CLOSED",
CASE "DATE_COMPLETED" WHEN "FLAG_CLOSED" << ??? >> = 'Y' THEN "DATE_COMPLETED" = '000000' END "DATE_COMPLETED"
FROM JOB_OPERATIONS

It looks like you're attempting to change the DATE_COMPLETED column in your table. You can't do that with a SELECT statement. CASE / WHEN / THEN helps construct output. UPDATE statements allow clauses like DATE_COMPLETED='000000' that change columns.
Try something like this.
SELECT "JOB", "SUFFIX", "SUFFIX", "DATE_COMPLETED", "FLAG_CLOSED",
CASE WHEN "FLAG_CLOSED"='Y' THEN '000000'
ELSE "DATE_COMPLETED" END "CLOSED_DATE_COMPLETED"
FROM "JOB_OPERATIONS"
I named your CASE-computed output column CLOSED_DATE_COMPLETED so it won't collide with the DATE_COMPLETED colum you already mentioned.

Syntax is either:
CASE a WHEN b
... or:
CASE when a=b
To return the value of DATE_COMPLETED depending on the flag, you can do this:
CASE "FLAG_CLOSED"
WHEN 'Y' THEN '000000'
ELSE "DATE_COMPLETED"
END AS "DATE_COMPLETED"
Beware that you need to produce a coherent column type. If DATE_COMPLETED is not text, you'll need to cast it.

Related

Case statement handling logic differently than expected

I'm trying to assign a status based on the number of IDs using a metric. This is the query I've written (and it works):
select
x.yyyy_mm_dd,
x.prov_id,
x.app,
x.metric,
x.is_100,
case
when ((x.is_100 = 'true') or size(collect_set(x.list)) >10) then 'implemented'
when ((x.is_100 = 'false') and size(collect_set(x.list)) between 1 and 10) then 'first contact'
else 'no contact'
end as impl_status,
size(collect_set(x.list)) as array_size,
collect_set(x.list) as list
from(
select
yyyy_mm_dd,
prov_id,
app,
metric,
is_100,
list
from
my_table
lateral view explode(ids) e as list
) x
group by
1,2,3,4,5
However, the impl_status is incorrect for the second condition in the case statement. In the result set, I can see rows with is_100 = false, array_size between 1 and 10, however the impl_status ends up being 'no contact' instead of 'first contact'. I was thinking maybe between isn't inclusive but it seems to be according to the docs.
I am curious if this works:
(case when x.is_100 or count(distinct x.list) > 10
then 'implemented'
when (not x.is_100) and count(x.list) > 0
then 'first contact'
else 'no contact'
end) as impl_status,
This should be the same logic without the string comparisons -- here is an interesting viewpoint on booleans in Hive. I also think that COUNT() is clearer than the array functionality.
Be sure you have not some hidden space in the string
when (( trim(x.is_100) = 'false') and size(collect_set(x.list)) between 1 and 10) then 'first contact'

how to prevent converting the text into boolean by the use of when statement in postgresql?

select fti.pa_serial_,fti.homeownerm_name,fti.ward_,fti.villagetole,fti.status,
ftrq.date_reporting, ftrq.name_of_recorder_reporting,
case
when fti.status='terminate' then ftrq.is_the_site_cleared ='1' end as is_the_site_cleared from fti join ftrq on ftrq.fulcrum_parent_id = fti.fulcrum_id
Here, is_the_site_cleared is text type of column which is converted into boolean by the when statement written and hence does not print as 1 and takes as true. I explicitly used print '1'. But this also did not work. My aim is to display '1' in the column 'is_the_site_cleared' when the value of fti.status='terminate'. Please help!!!
How about using integers rather than booleans?
select fti.pa_serial_, fti.homeownerm_name, fti.ward_,
fti.villagetole, fti.status, ftrq.date_reporting,
ftrq.name_of_recorder_reporting,
(case when fti.status = 'terminate' -- and ftrq.is_the_site_cleared = '1'
then 1 else 0
end) as is_the_site_cleared
from fti join
ftrq
on ftrq.fulcrum_parent_id = fti.fulcrum_id ;
From the description, I cannot tell if you want to include the condition ftrq.is_the_site_cleared = '1' in the when condition. But the idea is to have the then and else return numbers if that is what you want to see.

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.

SQL Server 2008 view error with case statement

I cant figure out why this code executes as a query but when I execute it in a view it throws a the multi-part identifier could not be bound, error.
When I take out the case statement It works in the view, so I believe it is something that has to do with the case statement.
Any suggestions are appreciated.
WITH [cteFrostSum] AS
(
SELECT ID AS ID, theMonth as Mo,
SUM(dbo.Frost.[DRAmount]) AS [DRAmount]
FROM dbo.Frost
GROUP BY [ID], theMonth
)
SELECT DISTINCT
TOP (100) PERCENT
dbo.ternean.MemberID,
dbo.ternean.SSN,
dbo.ternean.GroupName,
dbo.ternean.CustomerID,
dbo.ternean.GroupNumber,
dbo.ternean.LastName,
dbo.Frost.DRAmount,
dbo.Frost.HittheBank,
dbo.Frost.MonthofPremium,
cte.[DRAmount] AS [SUM_Frost_Balance],
dbo.ternean.TotalCost,
cte.[DRAmount] - dbo.ternean.TotalCost AS Diff,
dbo.ternean.ACH_RoutingNo,
dbo.Frost.RTNum,
dbo.ternean.ACH_AcctNo,
dbo.Frost.AccountNumber,
CASE
WHEN dbo.Frost.RTNum <> SUBSTRING(dbo.ternean.ACH_RoutingNo, 2, 20)
THEN 'DO not match'
WHEN dbo.Frost.RTNum = SUBSTRING(dbo.ternean.ACH_RoutingNo, 2, 20)
THEN 'match'
END AS [Routing # match],
CASE
WHEN SUBSTRING(dbo.ternean.ACH_AcctNo, 2, 20) <> dbo.Frost.AccountNumber
THEN 'DO not match'
WHEN SUBSTRING(dbo.ternean.ACH_AcctNo, 2, 20) = dbo.Frost.AccountNumber
THEN 'match'
END AS [Account # match],
dbo.Frost.theMonth
FROM dbo.Frost
INNER JOIN dbo.ternean ON dbo.Frost.ID = dbo.ternean.CustomerID
AND dbo.Frost.theMonth = dbo.ternean.theMonth
INNER JOIN [cteFrostSum] cte ON dbo.Frost.ID = cte.ID
AND dbo.Frost.theMonth = cte.Mo
ORDER BY dbo.ternean.theMonth
I tried to replicate your error but couldn't.
Why are you using multi-part identifiers the field names anyway? The list of fields in the select statement can only refer to the tables in the from clause, at first reading this query seems to be referring to the tables directly in the dbo schema.
Give your tables some nice easy aliases i.e.
FROM dbo.Frost AS F
and use them like this
F.RTNum
Secondly you can simplify your case statements and only do one test i.e.:
CASE WHEN SUBSTRING(T.ACH_AcctNo, 2, 20) <> F.AccountNumber
THEN 'DO not match'
ELSE 'match'
END AS [Account # match]