There is a procedure that gets the required data and then insert into table:
Is it possible to have a parameter that leads to certain filter condition, how can I achieve that?
For example, creating a new parameter called condition that if user type 1, the procedure will use filter 1 etc.
please see the code example below:
CREATE OR REPLACE PROCEDURE `peterwu.UDP_mem_profile_package`
(table_name STRING
, title_name STRING
, status_start_dt DATE
, status_end_dt DATE)
BEGIN
-- 2. insert data
EXECUTE IMMEDIATE format("""
INSERT INTO `peterwu..UDP_OUTPUT_mem_profile_aggregated`
(TITLE, GROUP_ORDER, GROUP_ID1, GROUP_NAME, MEM_CNT, TKT, SALES)
SELECT #title_name
, 5
, COUNT(DISTINCT MEM_ID) MEM_CNT
, COUNT(DISTINCT CASE WHEN IS_TICKET = 1 THEN TKT_NO END) AS TICKET
, SUM(retail_price_amt) SALES
FROM `peterwu.tlw_txn_since_2017`
WHERE TRANS_DT BETWEEN #start_dt AND #end_dt
AND MEM_ID IN (SELECT MEM_ID FROM `"""||table_name||"""`)
/*========== FILTER CONDITION CONTROLED BY USER INPUT: FILTER 1 OR FILTER 2=========*/
-- FILTER 1 --
AND
(
SITE_ID BETWEEN '1A01' AND '1A02' OR
SITE_ID BETWEEN '1A03' AND '1A04'
)
AND
-- FILTER 2 --
(
SITE_ID BETWEEN '1S01' AND '1S02' OR
SITE_ID BETWEEN '1S03' AND '1S04'
)
""")
USING status_start_dt as start_dt
, status_end_dt as end_dt
, title_name as title_name;
END
here's my sample code which is trying to do what you want.
basically to answer you question, it is possible to use conditional expression evaluated in the where clause. here I have assumed the input condition are two and can be assigned to two input variables and based on which where clause can be evaluated.
CREATE OR REPLACE PROCEDURE myproject.zz_DataSet.procTest
( title_name STRING
, condition1 string
, condition2 string)
BEGIN
EXECUTE IMMEDIATE format ("""
INSERT INTO myproject.zz_DataSet.zzProcTest (TITLE_NAME)
SELECT firstname
FROM myproject.zz_DataSet.tblOne
WHERE "condition1" = if(#c1 is null,#c2 ,#c1)
"""
)
USING condition1 as c1,
condition2 as c2;
END;
here's my call to procedure. in this case condition 1 is evaluated to true and hence inserts condition1 in table tblOne. hope this helps
call myproject.zz_DataSet.procTest("condition1","condition1","")
Related
I am trying to create a column with a case statement, then concatenate the column. Here is an example code.
WITH base AS (
SELECT ID, Date, Action, case when (Date is null then Action || '**' else Action End) Action_with_no_date
FROM <Table_Name>
)
SELECT ID, "array_join"("array_agg"(DISTINCT Action_with_no_date), ', ') Action_with_no_date
FROM base
GROUP BY ID;
Basically, the Action_with_no_date will display the concatenation of values in Action with '**' string added to the values where Date is null for each ID
After I did this, I found an edge case.
If there is the same Action (i.e. play) taken for one ID, and if one action has date and the other one doesn't, then the output will have one play and one play** for the ID
However, I want this to display just one play with **.
Below is the example data for ID = 1
ID Date Action
1 1/2/22 read
1 1/3/22 play
1 NULL play
and expected result for the ID
ID Action_with_no_date
1 read, play**
How should I handle this?
You can calculate ** suffix if there is any row with null per id and action using analytic max() with case expression. Then concatenate suffix with action.
Demo:
with mytable as (
SELECT * FROM (
VALUES
(1, '1/2/22', 'read'),
(1, '1/3/22', 'play'),
(1, NULL, 'play')
) AS t (id, date, action)
)
select id, array_join(array_agg(DISTINCT action||suffix), ', ')
from
(
select id, date, action,
max(case when date is null then '**' else '' end) over(partition by id, action) as suffix
from mytable
)s
group by id
Result:
1 play**, read
I'm having a hard time with sql and probably this will look stupid but it shows what I am trying to achieve.
SELECT
CASE WHEN ( ( SELECT 1 FROM table_1 WHERE = condition ) IS NULL ) THEN
SELECT 'No result'::varchar
ELSE
SELECT
val_1,
val_2,
val_3
FROM
table_1
END;
A null answer is not good in my situation, I can't just use the sub-query as the main. And even if I could that would still leave the question open if the two tables were NOT the same like:
SELECT
CASE WHEN ( ( SELECT 1 FROM table_1 WHERE = condition ) IS NULL ) THEN
SELECT 'No result'::varchar
ELSE
SELECT
val_1,
val_2,
val_3
FROM
table_2 --TABLE REPLACED!
END;
As CASE-WHEN only works for one column it would be horrifying to have 20 of them with the same condition. Any help is appreciated! Thanks!
So you want to SELECT the table_log and if the result is not NULL show it to the client and if it is NULL show a message?
I created a fake table for testing. What you are looking for is the last SELECT-statement:
DROP TABLE IF EXISTS table_log;
CREATE TEMP TABLE table_log (
id INTEGER
,log_info VARCHAR)
;
INSERT INTO table_log VALUES
(1, 'test_entry')
;
ANALYZE table_log;
SELECT
COALESCE(b.log_info, 'No changes done!') AS log_info
FROM
(SELECT 'Fake-Data') a
LEFT OUTER JOIN (SELECT * FROM table_log WHERE id = 1) b ON (1=1);
If the given id = 1, you get the result, if it is something else (because it is not in the test-table) the premade message is given.
Here is a link to the db<>fiddle.
It's the second question I'm asking for the same issue, so I'll try to be more specific and brief as I can.
In my pl/sql script, i try to insert into a table some records from lots of different tables. I achieve that, except for a field that comes from a JOIN of 2 tables.
The INSERT statement is placed into the following loop:
FOR FST_DEMAND_rec IN (
SELECT *
FROM A
WHERE FK_DEPOSIT_ACCOACC = DEPOSIT_ACC_rec.ACCOUNT_NUMBER
AND TRX_DATE BETWEEN '01-JAN-2018' AND '31-DEC-2018'
ORDER BY TRANS_SER_NUM , ENTRY_SER_NUM ASC)
LOOP
This loop is placed into the following cursor loop :
FOR T IN MOF_CURSOR LOOP
So the INSERT statement, which actually lies in 2 loops, is the following :
INSERT INTO MOF_OUT
VALUES(
T.MOF_REQUEST_ID,
LOC_SERIAL_NUM,
'2B',
CAST(FST_DEMAND_rec.TRX_UNIT || TO_CHAR(FST_DEMAND_rec.TRX_DATE,'YYYYMMDD') || FST_DEMAND_rec.TRX_USR || FST_DEMAND_rec.TRX_SN AS CHAR(50) ),
TO_CHAR(FST_DEMAND_rec.TRX_DATE,'YYYY-MM-DD') ,
CAST(FST_DEMAND_rec.TRX_UNIT AS CHAR(4) ) ,
UNIT_rec.UNIT_NAME ,
CAST(FST_DEMAND_rec.ID_TRANSACT AS CHAR(6) ),
PRFT_TRANS_rec.DESCRIPTION,
-- 'MY PROBLEMATIC FIELD'
TO_CHAR(FST_DEMAND_rec.TIMESTAMP,'hh24miss'),
FST_DEMAND_rec.ENTRY_AMOUNT,
LOC_DC_FLAG,
LOC_PROGR_BALANCE,
LOC_PROGR_BAL_IND
) ;
This INSERT statement works fine, but I don't know how to fill a record which comes from the following SELECT statement with the JOIN clause:
SELECT A.ENTRY_COMMENTS || ' ' || B.DESCRIPTION
FROM FST_DEMAND_EXTRAIT A INNER JOIN JUSTIFIC B ON A.ID_JUSTIFIC = B.ID_JUSTIFIC
For example, the PRFT_TRANS_rec variable that I use in the INSERT, it's declared as PRFT_TRANSACTION%ROWTYPE; and I have the following SELECT statement for it which is within these 2 loops :
SELECT *
INTO PRFT_TRANS_rec
FROM PRFT_TRANSACTION PRFT_TRANS
WHERE PRFT_TRANS.ID_TRANSACT = FST_DEMAND_rec.ID_TRANSACT;
I have a set of columns CODE_1-10, which contain diagnostic codes. I want to create a set of variables CODE_GROUP_1-17, which indicate whether or not one of some particular set of diagnostic codes matches any of the CODE_1-10 variables. For example, CODE_GROUP_1 = 1 if any of CODE_1-10 match either '123' or '456', and CODE_GROUP_2 = 1 if any of CODE_1-10 match '789','111','333','444' or 'foo'.
Here's an example of how you could do this using values constructors.
CASE WHEN (SELECT count(value.val)
FROM (VALUES (CODE_1)
, (CODE_2)
, (CODE_3)
, (CODE_4)
, (CODE_5)
, (CODE_6)
, (CODE_7)
, (CODE_8)
, (CODE_9)
, (CODE_10)
) AS value(val)
WHERE value.val in ('123', '456')
) > 0 THEN 1 ELSE 0 END AS CODE_GROUP_1,
CASE WHEN (SELECT count(value.val)
FROM (VALUES (CODE_1)
, (CODE_2)
, (CODE_3)
, (CODE_4)
, (CODE_5)
, (CODE_6)
, (CODE_7)
, (CODE_8)
, (CODE_9)
, (CODE_10)
) AS value(val)
WHERE value.val in ('789','111','333','444','foo')
) > 0 THEN 1 ELSE 0 END AS CODE_GROUP_2
I am wondering if there is another way to do this that is more efficient. Is there a way to make a CLR UDF that takes an array of CODE_1-10, and outputs a set of columns CODE_GROUP_1-17?
You could at least avoid the repetition of FROM (VALUES ...) like this:
SELECT
CODE_GROUP_1 = COUNT(DISTINCT CASE WHEN val IN ('123', '456') THEN 1 END),
CODE_GROUP_2 = COUNT(DISTINCT CASE WHEN val IN ('789','111','333','444','foo') THEN 1 END),
...
FROM
(
VALUES
(CODE_1),
(CODE_2),
(CODE_3),
(CODE_4),
(CODE_5),
(CODE_6),
(CODE_7),
(CODE_8),
(CODE_9),
(CODE_10)
) AS value(val)
If CODE_1, CODE_2 etc. are column names, you can use the above query as a derived table in CROSS APPLY:
SELECT
...
FROM
dbo.atable -- table containing CODE_1, CODE_2 etc.
CROSS APPLY
(
SELECT ... -- the above query
) AS x
;
Can you create 2 new tables with the columns appended as rows? So one table would be dxCode with a source column if you need to retain the 1-10 value and the dx code and whatever key field(s) you need, the other table would be dxGroup with your 17 groups, the source groupID if you need it, and your target dx values.
Then to determine which codes are in which groups, you can join on your dx fields.
I would like to ask if it is possible to create a SQL statement with an if or similar structure.
I have two queries and would like to combine them into one. The only difference between the two is that one has additional AND conditions on its WHERE clause.
I tried doing a select case, but was not very successful. I will create a parameter "test" that will take 1 or 2, and that condition should determine which query to run.
Here are the queries...
Query 1
SELECT ID,AVG(B.VOL) AS PVOL
FROM (SELECT VAR1 AS ID, SUM(VOL) AS PVOL FROM table1 WHERE VAR1='xyz'
AND DATE_D>'10/28/2013' AND DATE_D<'10/31/2013'
AND CUSTOMER='Market' AND MARKET='South' AND PROJECT=0
GROUP BY VAR1,DATE_D) B GROUP BY ID
Query 2
SELECT ID,AVG(B.VOL) AS PVOL
FROM (SELECT VAR1 AS ID, SUM(VOL) AS PVOL FROM table1 WHERE VAR1='xyz'
AND DATE_D>'10/28/2013' AND DATE_D<'10/31/2013'
AND PROJECT=0
GROUP BY VAR1,DATE_D) B GROUP BY ID
You could create a sproc that accepts the "test" parameter that you hope to build your IF statement around.
create procedure --sprocname
(
#test int
)
as
begin
set nocount on
if
#test = --bool
select statement 1
else
select statement 2
end
sorry for the poor format I was in a hurry setting it up
You can add the condition based on your parameter #test like below
same query can be used , based on the parameter the condition will be varied.
SELECT ID,AVG(B.VOL) AS PVOL
FROM (SELECT VAR1 AS ID, SUM(VOL) AS PVOL FROM table1 WHERE VAR1='xyz'
AND DATE_D>'10/28/2013' AND DATE_D<'10/31/2013'
AND ( (#test = 1 AND CUSTOMER='Market' AND MARKET='South' AND PROJECT=0 )
OR ( #test =2 AND PROJECT=0 )
)
GROUP BY VAR1,DATE_D) B GROUP BY ID