Using if statement in string_agg function - postreSQL - sql

The query is as follows
WITH notes AS (
SELECT 891090 Order_ID, False customer_billing, false commander, true agent
UNION ALL
SELECT 891091, false, true, true
UNION ALL
SELECT 891091, true, false, false)
SELECT
n.order_id,
string_Agg(distinct CASE
WHEN n.customer_billing = TRUE THEN 'AR (Customer Billing)'
WHEN n.commander = TRUE THEN 'AP (Commander)'
WHEN n.agent = TRUE THEN 'AP (Agent)'
ELSE NULL
END,', ') AS finance
FROM notes n
WHERE
n.order_id = 891091 AND (n.customer_billing = TRUE or n.commander = TRUE or n.agent = TRUE)
GROUP BY ORDER_ID
As you can see there are two records with order_id as 891091.
First 891091 record has commander and agent set as true
Second 891091 record has customer_billing set as true
Since switch case is used, it considers only the first true value and returns commander and does not consider agent.
So the output becomes
order_id finance
891091 AP (Commander), AR (Customer Billing)
dbfiddle.uk Example
I need all the true values in the record to be considered so that the output becomes
order_id finance
891091 AP (Commander), AP (Agent), AR (Customer Billing)
My initial thought is that using if statement instead of case statement may fix this. I am not sure how to do this inside string_agg function
How to achieve this?
EDIT 1:
The answer specified below works almost fine. But the issue is that the comma separated values are not distinct
Here is the updated fiddle
https://dbfiddle.uk/?rdbms=postgres_14&fiddle=9647d92870e3944516172eda83a8ac6e

You can consider splitting your case into separate ones and using array to collect them. Then you can use array_to_string to format:
WITH notes AS (
SELECT 891090 Order_ID, False customer_billing, false commander, true agent UNION ALL
SELECT 891091, false, true, true UNION ALL
SELECT 891091, true, true, false),
tmp as (
SELECT
n.order_id id,
array_agg(
ARRAY[
CASE WHEN n.customer_billing = TRUE THEN 'AR (Customer Billing)' END,
CASE WHEN n.commander = TRUE THEN 'AP (Commander)' END,
CASE WHEN n.agent = TRUE THEN 'AP (Agent)' END
]) AS finance_array
FROM notes n
WHERE
n.order_id = 891091 AND (n.customer_billing = TRUE or n.commander = TRUE or n.agent = TRUE)
GROUP BY ORDER_ID )
select id, array_to_string(array(select distinct e from unnest(finance_array) as a(e)), ', ')
from tmp;
Here is db_fiddle.

Related

Oracle Apex - Case within a where statement

I'm having issues while running the following query (interactive report / simplified the query cause I'm sure the issue is with the case statement):
select
v.manager_email
from my_table v
where
(
case
when :P28_ACT_AS_ROLE_H = 'Director' then v.director_email = :P28_ACT_AS_H
when :P28_ACT_AS_ROLE_H = 'Admin' then v.manager_email = nvl(:P28_ACT_AS_H,
v.manager_email)
when :P28_ACT_AS_ROLE_H = 'Manager' then v.manager_email = :P28_ACT_AS_H
end
)
The error is this one: ORA-20999.
Does someone know why this is happening?
(:p28 items are calculated via computations and work perfectly)
Thanks!
Don't use a case when boolean logic suffices:
where (:P28_ACT_AS_ROLE_H = 'Director' and v.director_email = :P28_ACT_AS_H) or
(:P28_ACT_AS_ROLE_H = 'Admin' and v.manager_email = nvl(:P28_ACT_AS_H, v.manager_email)) or
(:P28_ACT_AS_ROLE_H = 'Manager' and v.manager_email = :P28_ACT_AS_H)
The specific reason in your example is that Oracle doesn't recognize a boolean expression as a valid return value for a case, resulting in a syntax error
Or, with CASE:
where nvl(:P28_CT_AS_H, v.manager_email) =
case when :P28_ACT_AS_ROLE_H = 'Director' then v.director_email
when :P28_ACT_AS_ROLE_H = 'Admin' then v.manager_email
when :P28_ACT_AS_ROLE_H = 'Manager' then v.manager_email
end

Select cases from long table by key variable grouping

I have a table like below:
caseid | ncode | code | test
1 1 ABC TRUE
1 2 DEF TRUE
2 1 ABC TRUE
3 1 DEF TRUE
3 2 HIJ FALSE
Where caseid represents an individual case. This table creates the relationship that each individual case can have multiple codes associated with it (ncode and code). test is just a variable that tracks a boolean value of interest.
I have specific requirements for my query:
I need all cases where code = ABC and ncode = 1 and test = TRUE. This criteria has the highest priority.
Of those cases from #1, I need to create an additional column called hasdef that is a boolean that indicates if that specific caseid has any other rows where code = DEF and test = TRUE. It should be TRUE if so, otherwise FALSE.
So from the above table, what should return is:
caseid | ncode | code | test | hasdef
1 1 ABC TRUE TRUE
2 1 ABC TRUE FALSE
caseid = 1 returns because code = ABC, ncode = 1, and test = TRUE. hasdef = TRUE because in the second row, caseid = 1, code = DEF and test = TRUE.
caseid = 2 returns because code = ABC, ncode = 1, and test = TRUE. hasdef = FALSE because there is no other row with caseid = 2 where code = DEF.
caseid = 3 does not return. Even though there is a row where code = DEF and test = TRUE, the first criteria (code = ABC and ncode = 1) is not first satisfied.
This is what I have so far, but I am not confident it is working as desired:
select tab1.*, tab2.code is not null as hasdef from
(select * from mytable
where code = 'ABC' and ncode = 1) as tab1
left join (
select caseid, any_value(code) code, any_value(test) test
from mytable
group by caseid
having code = 'DEF' and test is true
) as tab2
using(caseid)
order by caseid
Below is for BigQuery Standard SQL
#standardSQL
select * from (
select *,
0 < countif(code = 'DEF' and test is true) over(partition by caseid) as hasdef
from `project.dataset.table`
)
where code = 'ABC' and ncode = 1 and test is true
if to apply to sample data from your question - output is
Note: you can replace test is true with just test as in below
select * from (
select *,
0 < countif(code = 'DEF' and test) over(partition by caseid) as hasdef
from `project.dataset.table`
)
where code = 'ABC' and ncode = 1 and test

Identifying products that a customer owns

I want to check whether my customer owns an iPhone, iPad, or Macbook.
I am not looking for how many iPhone or iPad or Macbook one customer has, I just want to identify if they own any of them, or if they own any two, or if they own all three.
I am thinking of using the CASE WHEN function and here is the query:
select customer
, case when AppleProduct = 'iPhone' THEN 'TRUE' ELSE 'FALSE END AS Owns_iPhone
, case when AppleProduct = 'iPad' THEN 'TRUE' ELSE 'FALSE AS Owns_iPad
, case when AppleProduct = 'Macbook' THEN 'TRUE' ELSE 'FALSE' AS Owns_Macbook
from Apple_Product_Ownership
This is the result that I am trying to get
customer | Owns_iPhone | Owns_iPad | Owns_Macbook
X TRUE TRUE FALSE
Y FALSE TRUE TRUE
Z TRUE FALSE FALSE
But this is what I am getting instead
customer | Owns_iPhone | Owns_iPad | Owns_Macbook
X TRUE FALSE FALSE
X FALSE TRUE FALSE
Y FALSE TRUE FALSE
Y FALSE FALSE TRUE
Z TRUE FALSE FALSE
You are looking for conditional aggregation. I would phrase your query as:
select
customer,
logical_or(AppleProduct = 'iPhone') Owns_iPhone,
logical_or(AppleProduct = 'iPad') Owns_iPad,
logical_or(AppleProduct = 'Macbook') Owns_Macbook,
from Apple_Product_Ownership
group by customer

pyspark.sql.utils.ParseException: u"\nextraneous > input 'xxx' expecting {')', ','}

I have 2 main tables: flights and holidays.
Flights is identified by: outboundlegid, inboundlegid, agent, querydatetime. The additional columns applicable to the question are out_date, in_date. They indicate when is the flight departing and the return date.
And Holidays with the columns start, end, type
I want to determine if the flight out/in date is intersecting any thing from holidays table.
I followed some suggestion from PySpark: How to add columns whose data come from a query (similar to subquery for each row) to determine if the out/in dates intersect any holiday.
However, I am getting: "pyspark.sql.utils.ParseException: u"\nextraneous
input 'outboundlegid' expecting {')', ','}(line 35, pos 12)". Whats wrong here?
File "script_2019-02-08-10-46-14.py", line 182, in """) File
"/mnt/yarn/usercache/root/appcache/application_1549622095592_0002/container_1549622095592_0002_01_000001/pyspark.zip/pyspark/sql/session.py",
line 603, in sql File
"/mnt/yarn/usercache/root/appcache/application_1549622095592_0002/container_1549622095592_0002_01_000001/py4j-0.10.4-src.zip/py4j/java_gateway.py",
line 1133, in call File
"/mnt/yarn/usercache/root/appcache/application_1549622095592_0002/container_1549622095592_0002_01_000001/pyspark.zip/pyspark/sql/utils.py",
line 73, in deco pyspark.sql.utils.ParseException: u"\nextraneous
input 'outboundlegid' expecting {')', ','}(line 35, pos 12)\n\n== SQL
==\n\n WITH t (\n SELECT \n f.outboundlegid,\n f.inboundlegid,\n f.agent,\n f.querydatetime,\n CASE WHEN type = 'HOLIDAY' AND (out_date
BETWEEN start AND end)\n THEN true\n ELSE false\n END
out_is_holiday,\n CASE WHEN type = 'LONG_WEEKENDS' AND (out_date
BETWEEN start AND end)\n THEN true\n ELSE false\n END
out_is_longweekends,\n CASE WHEN type = 'HOLIDAY' AND (in_date BETWEEN
start AND end)\n THEN true\n ELSE false\n END in_is_holiday,\n CASE
WHEN type = 'LONG_WEEKENDS' AND (in_date BETWEEN start AND end)\n THEN
true\n ELSE false\n END in_is_longweekends\n FROM flights f\n CROSS
JOIN holidays h\n )\n SELECT \n f.*,\n t1.out_is_holiday,\n
t1.out_is_longweekends,\n t1.in_is_holiday,\n t1.in_is_longweekends,\n
FROM (\n SELECT \n outboundlegid,\n------------^^^\n inboundlegid,\n
agent,\n querydatetime,\n CASE WHEN
array_contains(collect_set(out_is_holiday), true)\n THEN true\n ELSE
false\n END out_is_holiday,\n CASE WHEN
array_contains(collect_set(out_is_longweekends), true)\n THEN true\n
ELSE false\n END out_is_longweekends,\n CASE WHEN
array_contains(collect_set(in_is_holiday), true)\n THEN true\n ELSE
false\n END in_is_holiday,\n CASE WHEN
array_contains(collect_set(in_is_longweekends), true)\n THEN true\n
ELSE false\n
Whats the problem here?
resultDf = spark.sql("""
WITH t (
SELECT
f.outboundlegid,
f.inboundlegid,
f.agent,
f.querydatetime,
CASE WHEN type = 'HOLIDAY' AND (out_date BETWEEN start AND end)
THEN true
ELSE false
END out_is_holiday,
CASE WHEN type = 'LONG_WEEKENDS' AND (out_date BETWEEN start AND end)
THEN true
ELSE false
END out_is_longweekends,
CASE WHEN type = 'HOLIDAY' AND (in_date BETWEEN start AND end)
THEN true
ELSE false
END in_is_holiday,
CASE WHEN type = 'LONG_WEEKENDS' AND (in_date BETWEEN start AND end)
THEN true
ELSE false
END in_is_longweekends
FROM flights f
CROSS JOIN holidays h
)
SELECT
f.*,
t1.out_is_holiday,
t1.out_is_longweekends,
t1.in_is_holiday,
t1.in_is_longweekends,
FROM (
SELECT
outboundlegid, # <<< I am guessing something wrong with this? But Why?
inboundlegid,
agent,
querydatetime,
CASE WHEN array_contains(collect_set(out_is_holiday), true)
THEN true
ELSE false
END out_is_holiday,
CASE WHEN array_contains(collect_set(out_is_longweekends), true)
THEN true
ELSE false
END out_is_longweekends,
CASE WHEN array_contains(collect_set(in_is_holiday), true)
THEN true
ELSE false
END in_is_holiday,
CASE WHEN array_contains(collect_set(in_is_longweekends), true)
THEN true
ELSE false
END in_is_longweekends
FROM t
GROUP BY
querydatetime,
outboundlegid,
inboundlegid,
agent
LIMIT 100000
) t1
INNER JOIN flights f
ON t1.querydatetime = f.querydatetime
AND t1.outboundlegid = f.outboundlegid
AND t1.inboundlegid = f.inboundlegid
AND t1.agent = f.agent
INNER JOIN agents a
ON f.agent = a.id
INNER JOIN airports p
ON f.querydestinationplace = p.airportId
""")

IF Column has a value

I need to write sql query to check whether the column y in a table x has a value. In python I can check that like
object.y = 1
if object.y:
<statements>
Like this I need to check in Postgres
this is my query:
request.cr.execute(""" select * from x where parent_id = %s and nav_include = true and website_published = true and cms_lang = NULL and y is TRUE order by sequence""",([event_root]))
Here I need to check y has a value.
try this
request.cr.execute(""" select * from x where parent_id = %s and nav_include = true and website_published = true and cms_lang = NULL and coalesce(y, FALSE) is TRUE order by sequence""",([event_root]))
This is my solved answer
request.cr.execute(""" select * from x where parent_id = %s and nav_include = true and website_published = true and cms_lang is NULL and y is not null order by sequence""",([event_root]))
reference: https://www.techonthenet.com/postgresql/is_not_null.php