Postgresql update column when passed condition - postgresql

Is it possible, and if so, how can the following change be achieved?
Given the table:
param_tab
param_id serial
value integer
anothervalue integer
update_date TIMESTAMP
I would like to do something similar to this:
UPDATE param_tab pt
CASE WHEN CONDITION THEN pt.value = 14, pt.anothervalue = 20 END
pt.update_date = someTimestamp;
So update_date is always updated and value and anothervalue only in case of some condition

Use the CASE statement in the correct place:
UPDATE param_tab pt
SET value = CASE WHEN condition THEN 14 ELSE pt.value END,
anothervalue = CASE WHEN condition THEN 20 ELSE pt.anothervalue END,
update_date = someTimestamp;

Related

SQL Return a Value depending on 3 ranges of dates

I am having issues sorting some dates in 3 different ranges of dates and return a values according to the correct range. I am hoping you can give me a efficent and clean way of doing it.
I have 6 different dates that I get from a SQL Table. Those dates are then stored in variables. All the dates can also be a Null value. My dates are seperated in 3 date ranges. I want to return an indication of what ranges I am in by using the earliest start Date in all of my ranges. The date of the correct range must also be smaller than the current Date. A date Range can also consist of only an End Date. In that case, we considered that the range end at the end date and is active before that. We select the earliest end date that is close to the current Date in that case.
Return 0 if all the date are null
Range #1(Category #1) X Start Date and X end Date Return 1
Range #2(Category #2) Y Start Date and Y end Date Return 2
Range #3(Category #3) Z Start Date and Z end Date Return 3
EDIT
Ex#1 XStart = December 10 , XEnd = December 15
YStart = December 12 , Yend = December 13
ZStart = December 9 , ZEnd = Null
Expected result would be Z Category
Ex#2 XStart = December 8 , XEnd = December 15
YStart = NULL , Yend = NULL
ZStart = December 9 , ZEnd = Null
Expected result would be X Category
Ex#3XStart = NULL , XEnd = December 15
YStart = NULL , Yend = NULL
ZStart = December 9 , ZEnd = Null
Expected result would be X Category
Ex#4 XStart = December 10 , XEnd = December 15
YStart = NULL , Yend = NULL
ZStart = December 9 , ZEnd = Null
Expected result would be Z Category
Is there a more efficent way than doing a lot of IF statements ? I am having difficulty handling all of those conditions and checks. Here is a snippet of what I have so far.
--Return 0 is not Condition is Applicable
ALTER PROCEDURE [dbo].[HO_GetReason]
#HOID INT
AS
BEGIN
Declare #IsHOIDReal INT = (SELECT ID from T_HO where id = #HOID)
Declare #XStartDate Datetime
Declare #XEndDate Datetime
Declare #YStartDate Datetime
Declare #YEndDate Datetime
Declare #ZStartDate Datetime
Declare #ZEndDate Datetime
CREATE TABLE #tmpT_HO_Withhold (
ID INT NOT NULL,
XStartDate Datetime null,
XEndDate Datetime null,
YStartDate Datetime null,
YEndDate Datetime null,
ZStartDate Datetime null,
ZEndDate Datetime null,
PRIMARY KEY CLUSTERED (ID)
)
IF (#IsHOIDReal IS NOT NULL)
BEGIN
INSERT INTO #tmpT_HO_Withhold
SELECT T_HO.ID,
XStartDate ,
XEndDate ,
YStartDate ,
YEndDate ,
ZStartDate ,
ZEndDate
FROM dbo.T_HO
WHERE ID = #HOID
SET #XStartDate = (Select TOP 1 XStartDate from #tmpT_HO_Withhold)
SET #XEndDate = (Select TOP 1 XEndDate from #tmpT_HO_Withhold)
SET #YStartDate = (Select TOP 1 YStartDate from #tmpT_HO_Withhold)
SET #YEndDate = (Select TOP 1 YEndDate from #tmpT_HO_Withhold)
SET #ZStartDate = (Select TOP 1 ZStartDate from #tmpT_HO_Withhold)
SET #ZEndDate = (Select TOP 1 ZEndDate from #tmpT_HO_Withhold)
IF(#XStartDate IS NULL AND #YStartDate IS NULL AND #ZStartDate IS NULL)
BEGIN print 'NO CONDITION' Select 0 as 'HO_GetReason' END
ELSE IF (#XStartDate IS NOT NULL AND #YStartDate IS NULL AND #ZStartDate IS NULL) BEGIN print '1' Select 1 as 'HO_GetReason'END
ELSE IF (#XStartDate IS NOT NULL AND #YStartDate IS NULL AND #ZStartDate IS NULL) BEGIN print '2' Select 2 as 'HO_GetReason'END
ELSE IF (#XStartDate IS NULL AND #YStartDate IS NULL AND #ZStartDate IS NOT NULL) BEGIN print '3' Select 3 as 'HO_GetReason'END
END
DROP TABLE #tmpT_HO_Withhold END
Notes regarding efficient and clean:
Complex conditional are not in the inefficient category. It can fall into the hard to read category and maintain, but they are a pretty quick operation.
Example: That second "else if" looks strangely like the first "else if". Code will not be reached.
Creating and destroying the temp table will be the slowest part of your stored procedure.
Temp tables using #tablename are not concurrency safe in stored procedure, you can end up with odd schema altered errors in some cases.
You can get to the same results by swapping most of that with:
SELECT
#XStartDate = XStartDate ,
#XEndDate = XEndDate ,
#YStartDate = YStartDate ,
#YEndDate = YEndDate ,
#ZStartDate = ZStartDate ,
#ZEndDate = ZEndDate
FROM dbo.T_HO
WHERE ID = #HOID
Id is unique based on the primary key spotted in your create table, so TOP isn't necessary in this format, no rows will leave the values as null.
Personally, once I get that conditional working (absolute final form), I would be tempted to directly adjust it to a CASE statement and set that as a PERSISTENT computed COLUMN in the base table.
ALTER TABLE dbo.T_HO ADD Reason AS (CASE WHEN XStartDate IS NOT NULL AND ... THEN ... WHEN ... THEN ... ELSE 0 END) PERSISTED

how to add date in Teradata?

Hi i want to add 01/01/1970 to a column ,datatype of last_hit_time_gmt is bigint ,when i run the below query i am getting data type
last_hit_gmmt
does not match a defined datatype name.
select
distinct STG.OMN_APND_KEY,
STG.last_hit_time_gmt,
IIF(STG.last_hit_time_gmt <>0,ADD_TO_DATE(TO_DATE('01/01/1970', 'DD/MM/YYYY'),'SS',cast(STG.last_hit_time_gmt as DATE ),NULL)
from EDW_STAGE_CDM_SRC.STG_OMNITUREDATA STG
WHERE
UPPER(STG_OMNITUREDATA.EVAR41) IN
('CONS_SUPP: CONSUMER','STORE','PURCHASE') and
STG.OMN_APND_KEY='61855975'
please help me..
The query and data type is incompatible with Teradata.
As stated in the comments you may want to use "CASE" instead of "IFF". The general format is
CASE WHEN *condition* THEN *result_if_true*
ELSE *result_if_false*
END as *ColumnName*
editing based on comment response
So in your query example the case statement can be used like...
select distinct STG.OMN_APND_KEY
,STG.last_hit_time_gmt
,CASE WHEN STG.last_hit_time_gmt = 0 THEN NULL
ELSE DATE '1970-01-01'
END AS YourColName
FROM EDW_STAGE_CDM_SRC.STG_OMNITUREDATA STG
WHERE UPPER(STG_OMNITUREDATA.EVAR41) IN
('CONS_SUPP: CONSUMER','STORE','PURCHASE') and
STG.OMN_APND_KEY='61855975'
Also, if you are merely just trying to update the field STG.last_hit_time_gmt, why not just use two simple UPDATE statements?
UPDATE EDW_STAGE_CDM_SRC.STG_OMNITUREDATA
SET STG.last_hit_time_gmt = DATE '1970-01-01'
WHERE STG.last_hit_time_gmt <> 0
AND UPPER(STG_OMNITUREDATA.EVAR41) IN
('CONS_SUPP: CONSUMER','STORE','PURCHASE')
AND STG.OMN_APND_KEY='61855975';
UPDATE EDW_STAGE_CDM_SRC.STG_OMNITUREDATA
SET STG.last_hit_time_gmt = NULL
WHERE STG.last_hit_time_gmt = 0
AND UPPER(STG_OMNITUREDATA.EVAR41) IN
('CONS_SUPP: CONSUMER','STORE','PURCHASE')
AND STG.OMN_APND_KEY='61855975';

INSERT INTO not working in IF block - T-SQL

im working on procedure which should transfer number of items (value #p_count) from old store to new store
SET #countOnOldStore = (SELECT "count" FROM ProductStore WHERE StoreId = #p_oldStoreId AND ProductId = #p_productID)
SET #countOnNewStore = (SELECT "count" FROM ProductStore WHERE StoreId = #p_newStoreID AND ProductId = #p_productID)
SET #ShiftedCount = #countOnOldStore - #p_count
SET #newStoreAfterShift = #countOnNewStore + #p_count
IF #ShiftedCount > 0
BEGIN
DELETE FROM ProductStore WHERE storeId = #p_oldStoreId and productID = #p_productID
INSERT INTO ProductStore (storeId,productId,"count") VALUES (#p_oldStoreId,#p_productID,#ShiftedCount)
DELETE FROM ProductStore WHERE storeId = #p_newStoreID and productID = #p_productID
INSERT INTO ProductStore (storeId,productId,"count") VALUES (#p_newStoreID,#p_productID,#newStoreAfterShift)
END
ELSE
PRINT 'ERROR'
well ... second insert is not working. I cant figure it out. It says
Cannot insert the value NULL into column 'count', table 'dbo.ProductStore'; column does not allow nulls. INSERT fails.
Can anyone see problem and explain it to me ? Its school project
It looks like your entire query should just be:
UPDATE ProductStore
SET [count] = [count] + CASE
WHEN storeId = #p_NewStoreID THEN #p_Count
ELSE -#p_Count END
WHERE
productID = #p_ProductID and
storeID in (#p_NewStoreID,#p_OldStoreID)
If either value in the following is NULL, the total will be NULL:
SET #newStoreAfterShift = #countOnNewStore + #p_count
Check both values (#countOnNewStore, #p_count) for NULL.
Looks like you are not assigning any value to #p_count, so it is NULL and so are #ShiftedCount and #newStoreAfterShift.

How to set a bit based on a value existing in a table

I have a table. I have 2 variables, one is a bit, the other is an int.
Table: WorkGroupCollectionDetail
Variables: #WorkgroupID int, #IsFSBP bit
The table has WorkGroupId int PK and WorkGroupCollectionCode varchar PK. That's it.
I can run a query like this:
SELECT WorkGroupId
FROM WorkGroupCollectionDetail
WHERE WorkGroupCollectionCode = 'FSBP'
and it gives me a list of WorkGroupID.
So what I need to do is if the value of #WorkgroupID is inside the results of that query, I need to set the bit variable to true.
select #IsFBSP = case
when exists (
select 42 from WorkGroupDetailCollection
where WorkGroupCollectionCode = 'FSBP' and WorkGroupId = #WorkGroupId ) then 1
else 0 end
which is logically equivalent to:
select #IsFBSP = case
when #WorkGroupId in (
select WorkGroupId from WorkGroupDetailCollection
where WorkGroupCollectionCode = 'FSBP' ) then 1
else 0 end
A query using EXISTS often performs better than a query using IN. You can check the execution plans to see how they compare in your particular case.
Note that these examples include setting the bit value to zero as well as one.
You could modify the SELECT to include the check for the WorkGroupId and update the #IsFSBP accordingly:
IF EXISTS(SELECT WorkGroupId
FROM WorkGroupCollectionDetail
WHERE WorkGroupCollectionCode = 'FSBP'
AND WorkGroupId = #WorkgroupID)
BEGIN
SELECT #IsFSBP = 1;
END
SQL Fiddle example
I'm guessing you're looking for
Set #BitVariable = count(*)
From TestTable
WHERE TestCode = 'TestValue' and TestID = #TestID

need to translate specific t-sql case in pl/sql

Can anyone tell me how to translate the following T-SQL statement:
SELECT fileld1 = CASE
WHEN T.option1 THEN -1
ELSE
CASE WHEN T.option2 THEN 0
ELSE 1
END
END
FROM Table1 AS T
The point is I need to validate two different options from the table for a single field in the select statement..
I have tried to do somthing with an IF statement in pl/sql, but it just doesnt work for me:
SELECT IF T.option1 THEN -1
ELSE IF T.option2 THEN 0
ELSE 1
END
FROM Table1 AS T
I am not actually sure how to write IF statement inside the SELECT statement..
And also, I need to do it INSIDE the select statement because I am constructing a view.
Use:
SELECT CASE
WHEN T.option1 = ? THEN -1
WHEN T.option2 = ? THEN 0
ELSE 1
END AS field1
FROM Table1 AS T
I can't get your original TSQL to work - I get:
Msg 4145, Level 15, State 1, Line 4
An expression of non-boolean type specified in a context where a condition is expected, near 'THEN'.
...because there's no value evaluation. If you're checking if the columns are null, you'll need to use:
SELECT CASE
WHEN T.option1 IS NULL THEN -1
WHEN T.option2 IS NULL THEN 0
ELSE 1
END AS field1
FROM Table1 AS T
...or if you need when they are not null:
SELECT CASE
WHEN T.option1 IS NOT NULL THEN -1
WHEN T.option2 IS NOT NULL THEN 0
ELSE 1
END AS field1
FROM Table1 AS T
CASE expressions shortcircuit - if the first WHEN matches, it returns the value & exits handling for that row - so the options afterwards aren't considered.
If I remember correctly, PL/SQL also supports the case. You just would have to move the column alias from "field1=" before the expression to "AS filed1" after the expression.