PostgreSQL: Add condition in where clause using CASE - postgresql

I am using PostgreSQL 8.2 and I am also new to PostgreSQL.
I have to add one condition in the WHERE clause depending upon specific value (49) of the field (activity.type). Here is my Query:
SELECT activity.*
FROM activity
LEFT JOIN event_types ON activity.customstatusid = event_types.id, getviewableemployees(3222, NULL) AS report
WHERE
(
CASE WHEN activity.type = 49 THEN
'activity.individualid IN(SELECT individualid from prospects where prospects.individualid = activity.individualid)'
ELSE 1
END
)
AND activity.date BETWEEN '2016-10-01' AND '2016-10-06'
AND activity.type IN (21, 22, 49, 50, 37, 199)
AND (event_types.status = 1 or event_types.status IS NULL);
When I run above query in the command line access of PGSQL then I get below error:
ERROR: invalid input syntax for integer: "activity.individualid IN(SELECT individualid from prospects where prospects.individualid = activity.individualid)"
What I am missing here?

Implement your where clause as:
WHERE (
activity.type != 49 OR
activity.individualid IN (
SELECT individualid from prospects
WHERE prospects.individualid = activity.individualid)
)
AND activity.date BETWEEN '2016-10-01' AND '2016-10-06'
AND activity.type IN (21, 22, 49, 50, 37, 199)
AND (event_types.status = 1 or event_types.status IS NULL);
The first clause will only be true when either:
activity.type != 49; or
activity.type == 49 and activity.individualid is found in the subquery.

Related

Database migration syntax

I am unsure how to rewrite this. I understand the issue or at least I think I do. I am unable to use instances of t before it is defined by the follow "AS" statement. How can I resolve this so that so that it works the same way without using the instance of t before definition?
The error that I am getting thrown from the converter is "unable to convert .t"
Converted code
INSERT INTO t$trades_long (portfolio_name, fund, cusip, td_num, desc_instmt, trd_price, trd_trade_dt, t.trd_settle_dt, trd_counterparty, trd_td_par, tran_type, sec_type, trd_type, t.trd_trader)
SELECT
p.portfolio_name, t.fund, t.cusip, t.td_num, a.desc_instmt, t.trd_price, t.trd_trade_dt, t.trd_settle_dt, t.trd_counterparty, t.trd_td_par, t.tran_type, a.sec_type, 'long' AS trd_type, trd_trader
FROM pfi_pilot.br_transaction AS t, pfi_pilot.br_portfolio_group AS p, pfi_pilot.br_asset AS a
WHERE t.fund = p.fund AND p.portfolio_group = 'ALL_FUNDS' AND t.cusip = a.cusip AND t.tran_type IN ('BUY', 'SELL', 'ISSUE', 'ALLOC') AND t.trd_status <> 'C' AND a.sm_sec_group NOT IN ('CASH', 'FUTURE', 'FX', 'FUND', 'SWAP', 'OPTION') AND a.sec_type != 'MBS_TBA' AND t.trd_counterparty NOT IN ('IFUND', 'GHOST', 'SPO', 'SPOBO', 'CONV', 'ASSGN') AND t.trd_trade_dt >= par_from_dt AND t.trd_trade_dt <= par_to_dt AND t.cusip NOT IN (SELECT DISTINCT
cusip
FROM pfi_pilot.br_asset
WHERE (COALESCE(risk_country, country) = 'US' AND sm_sec_type IN ('GOVT', 'TBILL'))) AND t.trd_td_par > 0;
Original code
insert into #trades_long(portfolio_name, fund, cusip, td_num, desc_instmt, trd_price, trd_trade_dt, t.trd_settle_dt,
trd_counterparty, trd_td_par, tran_type , sec_type, trd_type, t.trd_trader)
select p.portfolio_name, t.fund, t.cusip, t.td_num, a.desc_instmt, t.trd_price, t.trd_trade_dt, t.trd_settle_dt,
t.trd_counterparty, t.trd_td_par, t.tran_type, a.sec_type,'long' as trd_type, trd_trader
from br_transaction t, br_portfolio_group p, br_asset a
where t.fund = p.fund
and p.portfolio_group = 'ALL_FUNDS'
and t.cusip = a.cusip
and t.tran_type in ('BUY','SELL','ISSUE','ALLOC')
and t.trd_status <> 'C'
and a.sm_sec_group not in ('CASH','FUTURE','FX','FUND','SWAP','OPTION')
and a.sec_type != 'MBS_TBA'
and t.trd_counterparty not in ('IFUND','GHOST','SPO','SPOBO','CONV','ASSGN')
and t.trd_trade_dt >= #from_dt
and t.trd_trade_dt <= #to_dt
and t.cusip not in (select distinct cusip from br_asset where (isnull(risk_country,country) = 'US'
and sm_sec_type in ('GOVT','TBILL')))
and t.trd_td_par > 0

how to query postgres jsonb for following json and make it available as part of the result

I have the following record as a jsonb field in a PG13 table
meta
{"subscriptions": [{"location_id": 14555, "practice_area_id": 39, "monthly_quota_views": 300, "remaining_views": 300},
{"location_id": 14832, "practice_area_id": 39, "monthly_quota_views": 250, "remaining_views": 250},
{"location_id": 17793, "practice_area_id": 39, "monthly_quota_views": 700, "remaining_views": 700}]}
I'd like to query for location_id: 14555, practice_area_id: 39 and having remaining_views > 0. Also, I'd like to return the selected hash from the array as part of the result (if possible).
I have
SELECT * FROM mytable WHERE
meta->'subscriptions' #> '[{"location_id":14555}]' and
meta->'subscriptions' #> '[{"practice_area_id":39}]';
but how would I check for remaining_views > 0 and return that selected hash as part of the result? Is there a less bulky way of writing this query? Thanks
I suspect by "return the selected hash from the array" you refer to the object that is contained in the subscriptions array.
There are two ways to do this:
use jsonb_array_elements to get the individual objects:
SELECT *
FROM pg13,
LATERAL jsonb_array_elements(pg13.meta -> 'subscriptions') el
WHERE el->>'location_id' = '14555'
AND el->>'practice_area_id' = '39'
AND (el->>'remaining_views')::int > 0
use a json path query:
SELECT *, jsonb_path_query(meta, '$.subscriptions[*] ? (#.location_id == 14555 && #.practice_area_id == 39 && #.remaining_views > 0)')
FROM pg13
You can use a JSON path expression to filter the desired elements and also return only those:
select jsonb_path_query_array(meta, '$.subscriptions[*] ? (#.location_id == 14555 && #.practice_area_id == 39 && #.remaining_views > 0)')
from the_table
where meta #? '$.subscriptions[*] ? (#.location_id == 14555 && #.practice_area_id == 39 && #.remaining_views > 0)';
Based on your sample data, the above returns:
jsonb_path_query_array
----------------------------------------------------------------------------------------------------
[{"location_id": 14555, "remaining_views": 300, "practice_area_id": 39, "monthly_quota_views": 300}]
If you are certain there will be only one element matching your condition, you can use jsonb_path_query_first() instead

Postgresql update column with integer values

I've a column with jsonb type and contains list of elements either in string or integer format.
What I want now is to make all of them as same type e.g either all int or all string format
Tried: this way I get single element but I need to update all of the elements inside of the list.
SELECT parent_path -> 1 AS path
FROM abc
LIMIT 10
OR
Update abc SET parent_path = ARRAY[parent_path]::TEXT[] AS parent_path
FROM abc
OR
UPDATE abc SET parent_path = replace(parent_path::text, '"', '') where id=123
Current Output
path
[6123697, 178, 6023099]
[625953521394212864, 117, 6023181]
["153", "6288361", "553248635949090971"]
[553248635358954983, 178320, 174, 6022967]
[6050684, 6050648, 120, 6022967]
[653, 178238, 6239135, 38, 6023117]
["153", "6288496", "553248635977039112"]
[553248635998143523, 6023185]
[553248635976194501, 6022967]
[553248635976195634, 6022967]
Expected Output
path
[6123697, 178, 6023099]
[625953521394212864, 117, 6023181]
[153, 6288361, 553248635949090971] <----
[553248635358954983, 178320, 174, 6022967]
[6050684, 6050648, 120, 6022967]
[653, 178238, 6239135, 38, 6023117]
[153, 6288496, 553248635977039112] <----
[553248635998143523, 6023185]
[553248635976194501, 6022967]
[553248635976195634, 6022967]
Note: Missing double quotes on the list. I've tried several methods from here but no luck
You will have to unnest them, cleanup each element, then aggregate it back to an array:
The following converts all elements to integers:
select (select jsonb_agg(x.i::bigint order by idx)
from jsonb_array_elements_text(a.path) with ordinality as x(i, idx)
) as clean_path
from abc a;
You can use a scalar subquery to select, unnest, and aggregate the elements:
WITH mytable AS (
SELECT row_number() over () as id, col::JSONB
FROM (VALUES ('[6123697, 178, 6023099]'),
('["6123697", "178", "6023099"]')) as bla(col)
)
SELECT id, (SELECT JSONB_AGG(el::int) FROM jsonb_array_elements_text(col) as el)
FROM mytable

I keep getting a unexpected select error in my snosql statement

I keep getting an unexpected select error as well as an unexpected ON error in rows 61 AND 64 in my snowsql statement.
Not sure why if anyone can help that would be great. I've added the portion of my snowsql statement below.
I'm trying to use a select statement within a where clause is there a way to do this?
AS select
t1.sunday_date,
t1.sunday_year_month,
t1.sunday_month,
t1.dc,
t1.source_sku,
t1.Product_Family,
t1.Product_type,
t1.Product_Subtype,
t1.Material,
t1.Color,
t1.Size,
t1.EOL_Date,
t1.NPI_Date,
t1.period_start,
t1.period_month,
IIF( t4.period_start < t1.sunday_date, iif(ISNULL(ta.actual_quantity), 0, ta.actual_quantity),
IIF(ISNULL(tfc.SOPFCSTOVERRIDE ), iif(ISNULL(tf.Period_Start), 0, tf.dc_forecast) , tfc.SOPFCSTOVERRIDE
)) AS forecast_updated,
iif(ISNULL(tf.Period_Start),t4.period_start,tf.Period_Start) AS period_start_forecast,
iif(ISNULL(ti.VALUATED_UNRESTRICTED_USE_STOCK), 0, ti.VALUATED_UNRESTRICTED_USE_STOCK) AS inventory_quantity,
iif(ISNULL(ti.HCI_DS_KEYFIGURE_QUANTITY), 0, ti.HCI_DS_KEYFIGURE_QUANTITY) AS in_transit_quantity,
iif(ISNULL(ti.planned_quantity), 0, ti.planned_quantity) AS inbound_quantity,
iif(ISNULL(tbac.backlog_ecomm ), 0, tbac.backlog_ecomm) + iif(ISNULL(tbac_sap.backlog_sap_open), 0, tbac_sap.backlog_sap_open) AS backlog_quantity,
iif(ISNULL(ta.actual_quantity), 0, ta.actual_quantity) AS actual_quantity,
iif(ISNULL(tso.open_orders), 0, tso.open_orders) AS open_orders,
iif(ISNULL(tf.Period_Start), 0, tf.dc_forecast) AS forecast,
tfc.SOPFCSTOVERRIDE AS forecast_consumption,
iif(ISNULL(tpc.SHIP_DATE), 0, tpc.SHIP_DATE) AS production_current_week,
iif(ISNULL(tpc.SHIP_DATE), 0, tpc.SHIP_DATE) AS production_next_week,
NOW() AS updated_timestamp
FROM ( ( ( ( ( ( ( ( (
SELECT
e.sunday_date,
e.sunday_month,
e.sunday_year_month,
d.dc,
c.SOURCE_SKU,
c.Product_Family,
c.Product_Type,
c.Product_Subtype,
c.Material,
c.Color,
c.Size,
c.EOL_Date,
c.NPI_Date,
b.period_start,
b.period_month
FROM
(SELECT sunday_date, sunday_month, sunday_year_month FROM bas_report_date) AS e,
(SELECT distinct Week_Date AS period_start, DateSerial('445_Year','445_Month',1) AS period_month from inv_bas_445_Month_Alignment) AS b,
(SELECT source_sku AS source_sku, Product_Family, Product_Type, Product_Subtype, Material, Color, Size, EOL_Date, NPI_Date from inv_vw_product_dev ) AS c,
(SELECT dc AS dc FROM inv_bas_dc_site_lookup) AS d
WHERE b.period_start >=
( select
MIN(mt.Reference_Date )
FROM BAS_report_date tr
INNER JOIN inv_bas_445_Month_Alignment mt ON tr.sunday_month = DateSerial(mt.'445_Year',mt.'445_Month,1')
)
AND b.period_start <= DateAdd("ww", 26,e.sunday_date)
) t1
LEFT JOIN
(
SELECT
MATERIAL_NUMBER,
CINT(LOCATION_NUMBER) AS Int_Location_ID,
HCI_DS_KEYFIGURE_DATE,
HCI_DS_KEYFIGURE_QUANTITY,
PLANNED_QUANTITY,
VALUATED_UNRESTRICTED_USE_STOCK
FROM inv_vw_ibp_transit_inventorry_dev
) ti
You can replace the DateSerial() function
(which is from VBA / MS Access / Excel from the Microsoft universe)
with DATE_FROM_PARTS().
DATE_FROM_PARTS() also supports the non-obvious functionality of DateSerial():
DateSerial(2020, 1, 1 - 1) gets you New Year's Eve - the day before New Year's Day
DATE_FROM_PARTS(2020, 1 - 1, 1 - 1) is the month before the day before New Year's Day
DATE_FROM_PARTS(y, m + 1, 0) is End Of Month (EOM).
etc., etc.

using IF statement with update clause in pgsql

I want to add a condition in update I am really not sure how to do it.
I want to do following:
UPDATE
xyz_table
SET
cap = some_text, IF (some_text IS NULL) THEN some_text = alternate_text ENDIF
WHERE
alternate_text <> '' AND
cap IS NULL AND
some_relation_id IN ( 50, 51, 52 );
If there is really any way to do this, please suggest else I think I will need to execute same query twice to achieve this.
Thanks in Advance :)
You can use case or coalesce(). This is the set statement:
SET cap = some_text,
some_text = COALESCE(some_text, alternate_text)
that should do:
UPDATE
xyz_table
SET
cap = some_text, some_text = (case when some_text IS NULL THEN alternate_text else some_text end)
WHERE
alternate_text <> '' AND
cap IS NULL AND
some_relation_id IN ( 50, 51, 52 );
dont forget to BEGIN transaction before running
In your particular example, the simplest way would be using IsNull().
UPDATE
xyz_table
SET cap = ISNULL(some_text, alternate_text)
WHERE alternate_text <> '' AND
cap IS NULL AND
some_relation_id IN ( 50, 51, 52 );
for other conditions, I tend to use a case statement.
UPDATE
xyz_table
SET cap = CASE WHEN some_text = '' THEN alternate_text ELSE some_text END
WHERE alternate_text <> '' AND
cap IS NULL AND
some_relation_id IN ( 50, 51, 52 );