encountered ")." was expecting one of "as" in teradata - teradata

I am getting above mentioned error while executing a query against Teradata Studio express
select
Union16.Item as Item,
Union16.Description as Description,
Union16.Nbr_Trans as Nbr_Trans,
Union16.Unit_price as Unit_price,
Union16.Amount as Amount,
MIN(Union16.Amount) as Total_Amount_
from (select AL1.ticket_document_number as ticket_document_number,
AL1.transaction_code as transaction_code,
AL1.void_status as void_status,
AL1.transaction_date as transaction_date,
AL1.pnr_record_locator as pnr_record_locator,
AL1.settlement_base_fare_amt as settlement_base_fare_amt,
AL1.settlement_total_tax_amt as settlement_total_tax_amt,
AL1.Multiplier as Multiplier,
(AL1.Multiplier * 2) as Service_Incentive_Fee,
(AL1.Multiplier * 2) as Transaction_Fee,
(case when AL1.TRANSACTION_CODE = 'ET' and AL1.VOID_STATUS = 'N' then 1
when AL1.TRANSACTION_CODE = 'RF' and AL1.VOID_STATUS = 'N' then -1
else 0
end) as NetTrans,
0 as Comm_Amount,
SUM(1) as Total_Trans,
AL1.period_end_date as period_end_date,
SUM(NetTrans * 2) as Service_Fee_due,
AL1.airline_code as airline_code,
1 as Item,
(('Supplier Link Service Incentive Fee # $' || '2') || '/Tix') as Description,
2 as Unit_price,
SUM(NetTrans * 2) as Amount,
SUM(NetTrans * 2) as Transaction_Fee_due,
SUM((NetTrans * 2) + (NetTrans * 2)) as Total_Due,
SUM(1) as Total_Total_Trans_,
SUM(NetTrans * 2) as Total_Service_Fee_due_,
SUM(NetTrans * 2) as Total_Transaction_Fee_due_,
SUM((NetTrans * 2) + (NetTrans* 2)) as Total_Total_Due_,
SUM(NetTrans) as Net_Trans,
SUM(NetTrans) as Total_Net_Trans_,
SUM(NetTrans) as Nbr_Trans
from (SELECT LAST_DAY(AL1.period_end_date) AS PEDHEADER,
AL1.TICKET_DOCUMENT_NUMBER as TICKET_DOCUMENT_NUMBER ,
(case when AL1.TRANSACTION_CODE = 'ET' and AL1.VOID_STATUS = 'N' then 1
when AL1.TRANSACTION_CODE = 'RF' and AL1.VOID_STATUS = 'N' then -1
else 0
end) as NetTrans,
(case
when AL1.VOID_STATUS = 'V' then 0
when AL1.VOID_STATUS <> 'V' and AL1.TRANSACTION_CODE in ('AT','ET') then 1
when AL1.VOID_STATUS <> 'V' and AL1.TRANSACTION_CODE = 'RF' then -1
when AL1.VOID_STATUS <> 'V' and AL1.TRANSACTION_CODE not in ('AT','ET','RF') then 0
end
) as Multiplier,
AL1.TRANSACTION_CODE as TRANSACTION_CODE ,
AL1.VOID_STATUS as VOID_STATUS,
cast(AL1.TRANSACTION_DATE as date) as TRANSACTION_DATE ,
AL1.PNR_RECORD_LOCATOR as PNR_RECORD_LOCATOR ,
AL1.SETTLEMENT_BASE_FARE_AMT as SETTLEMENT_BASE_FARE_AMT ,
AL1.SETTLEMENT_TOTAL_TAX_AMT as SETTLEMENT_TOTAL_TAX_AMT,
cast(AL1.PERIOD_END_DATE as date) as PERIOD_END_DATE ,
AL1.AIRLINE_CODE as AIRLINE_CODE,
airline_name as airline_name ,
SUM (1 ) as Total_records,
0 as Total_comm_due,
SUM ((Multiplier * 2) ) as total_serv_inc_fee,
SUM ((Multiplier * 2) ) as total_trans_fee_due,
((0 + SUM((Multiplier * 2) )) + SUM((Multiplier * 2) )) as Total_amt_due,
0 as Comm_Amount,
(Multiplier * 2) as Service_Incentive_Fee,
(Multiplier * 2) as Transaction_Fee,
1 as cntr
FROM ODS_VIEWS.BOP_ARC_SETTLEMENT AL1
LEFT OUTER JOIN
(select tabC.refvalcode, tabC.acct_cd, tabC.airline_name, tabC.refvaltm
from (select ref1.refvalcode , max(case when ref1.refvalattribcode='numericCode' then ref1.refvalvalue else null end) as acct_cd,
max(case when ref1.refvalattribcode='Codedescription' then ref1.refvalvalue else null end) as airline_name,
tabA.refvaltm
from bial.refvalue ref1, (select refvalcode, refvalvalue as airline_name, max(refvalueid) as "refvaltm"
from bial.refvalue
where refvalcodesetcode='Carrier'
and refvalattribcode='Codedescription'
group by refvalcode, refvalvalue) tabA
where tabA.refvalcode = ref1.refvalcode
and ref1.refvalcodesetcode='Carrier'
group by ref1.refvalcode, tabA.refvaltm ) tabC
,
(select tabB.acct_cd, max(tabB.refvaltm) as "refvaltm"
from (select ref1.refvalcode , max(case when ref1.refvalattribcode='numericCode' then ref1.refvalvalue else null end) as acct_cd,
max(case when ref1.refvalattribcode='Codedescription' then ref1.refvalvalue else null end) as airline_name,tabA.refvaltm
from bial.refvalue ref1, (select refvalcode, refvalvalue as airline_name, max(refvalueid) as "refvaltm"
from bial.refvalue
where refvalcodesetcode='Carrier'
and refvalattribcode='Codedescription'
group by refvalcode, refvalvalue) tabA
where tabA.refvalcode = ref1.refvalcode
and ref1.refvalcodesetcode='Carrier'
group by ref1.refvalcode, tabA.refvaltm ) tabB
group by tabB.acct_cd
) tabD
where tabC.refvaltm = tabD.refvaltm
and tabC.acct_cd = tabD.acct_cd
) AIRDET
ON AL1.AIRLINE_CODE = AIRDET.acct_cd
WHERE cast(AL1.PERIOD_END_DATE as date) BETWEEN 01-01-2015 AND 31-01-2015
AND AL1.FILE_TYPE='AM'
AND AL1.SUPPLIER_LINK_INDICATOR='D'
AND AIRLINE_NAME = 'Alaska Airlines'
AND AL1.oltp_deleted_timestamp IS NULL
group by
AL1.period_end_date ,
AL1.TICKET_DOCUMENT_NUMBER,
NetTrans ,
Multiplier ,
AL1.TRANSACTION_CODE,
AL1.VOID_STATUS,
AL1.TRANSACTION_DATE,
AL1.PNR_RECORD_LOCATOR,
AL1.SETTLEMENT_BASE_FARE_AMT,
AL1.SETTLEMENT_TOTAL_TAX_AMT,
AL1.AIRLINE_CODE,
airline_name,
Total_comm_due,
Comm_Amount,
Service_Incentive_Fee,
Transaction_Fee,
cntr,
AL1.oltp_deleted_timestamp,
AL1.SUPPLIER_LINK_INDICATOR,
AL1.FILE_TYPE,
AL1.AIRLINE_CODE
)
) Union16
group by
Union16.Item,
Union16.Description,
Union16.Nbr_Trans,
Union16.Unit_price,
Union16.Amount
order by
Item asc,
Description asc;

Simply you have close look at the query editor. You will notice that Teradata Studio marks the position of the error.
There's an alias missing for the Derived Table before ) Union16

Related

How to get the current_row in a main query for a subquery?

Let assume the following table:
CREATE TABLE t1 (col1 TEXT PRIMARY KEY, value INTEGER);
INSERT INTO t1 VALUES
('IE/a', 1), ('IE/b', 2), ('IE/c', 3) ,
('00/a', 10), ('01/a', 20), ('02/a', 30), ('03/a', 40),
('00/b', 100), ('01/b', 200), ('02/b', 300), ('03/b', 400),
('00/c', 1000), ('01/c', 2000), ('02/c', 3000), ('03/c', 4000);
The content of the table is:
col1 value
IE/a 1
IE/b 2
IE/c 3
00/a 10
01/a 20
02/a 30
03/a 40
00/b 100
01/b 200
02/b 300
03/b 400
00/c 1000
01/c 2000
02/c 3000
03/c 4000
I want to get the following output:
IE/a 100
IE/b 1000
IE/c 10000
So, IE/a is the sum of the values of 00/a + 01/a + 02/a + 03/a.
My first approach looks like this, where current_row_id as my pseudeo_code_variable to demonstrate that a would like to consider the current row:
SELECT
col1
, (SELECT sum(value) FROM t1
WHERE col1 = '00' || SUBSTRING( current_row_col1, 3)
OR col1 = '01' || SUBSTRING( current_row_col1, 3)
OR col1 = '02' || SUBSTRING( current_row_col1, 3)
OR col1 = '03' || SUBSTRING( current_row_col1, 3)
) AS value
FROM t1
WHERE col1 LIKE 'IE/%';
Use a self join and aggregation:
SELECT t1.col1,
TOTAL(t2.value) AS total
FROM tablename t1 LEFT JOIN tablename t2
ON SUBSTR(t2.col1, INSTR(t2.col1, '/') + 1) = SUBSTR(t1.col1, INSTR(t1.col1, '/') + 1)
AND t2.rowid <> t1.rowid
WHERE t1.col1 LIKE 'IE/%'
GROUP BY t1.col1;
Or, with conditional aggregation:
SELECT MAX(CASE WHEN col1 LIKE 'IE/%' THEN col1 END) AS col1,
TOTAL(CASE WHEN col1 NOT LIKE 'IE/%' THEN value END) AS total
FROM tablename
GROUP BY SUBSTR(col1, INSTR(col1, '/') + 1);
Or, with window functions:
SELECT DISTINCT
MAX(CASE WHEN col1 LIKE 'IE/%' THEN col1 END) OVER (PARTITION BY SUBSTR(col1, INSTR(col1, '/') + 1)) AS col1,
TOTAL(CASE WHEN col1 NOT LIKE 'IE/%' THEN value END) OVER (PARTITION BY SUBSTR(col1, INSTR(col1, '/') + 1)) AS total
FROM tablename;
See the demo.
This should give you your expected results.
Remember when working with additional categories like ['IE/g'] you will need to add last letters to the conditional statement in where clause.
I used val instead of value as a column name because in many DBMS it's a restricted keyword.
Code:
select 'IE/' || substr(col1,4,1) col, sum(val) my_sum from t1 where col1 LIKE '%/%' and col1 not like 'IE/%' and substr(col1,4,1) in ('a', 'b', 'c') group by substr(col1,4,1);
Output:
col my_sum
IE/a 100
IE/b 1000
IE/c 10000

WITH RECURSIVE looping through every day in the database and SUM number between two dates for each

I struggle with the last part below, the "with recursive". Of course I could loop over TimestampOrigin using C#, for every day in the database. Which would mean hundreds of times the same query. But it may be possible with one query using "with recursive".
Test data:
CREATE TABLE tblData(
Id INT, ComputerName TEXT, TimestampOrigin TEXT, Timestamp TEXT, Number INT
);
DELETE FROM tblData;
INSERT INTO tblData VALUES (1, "Computer1", '2021-02-10 12:00:00', '2021-02-27 12:00:00', 35);
INSERT INTO tblData VALUES (2, "Computer2", '2021-02-10 12:00:00', '2021-02-27 12:00:00', 24);
INSERT INTO tblData VALUES (3, "Computer3", '2021-02-09 12:00:00', '2021-02-26 12:00:00', 23);
INSERT INTO tblData VALUES (3, "Computer4", '2021-02-09 12:00:00', '2021-02-26 12:00:00', null);
INSERT INTO tblData VALUES (4, "Computer5", '2021-02-08 12:00:00', '2021-02-25 12:00:00', 7);
INSERT INTO tblData VALUES (5, "Computer6", '2021-02-08 12:00:00', '2021-02-25 12:00:00', 0);
INSERT INTO tblData VALUES (7, "Computer7", '2021-02-07 12:00:00', '2021-02-24 12:00:00', 9);
Query grouped by TimestampOrigin:
SELECT DATE(TimestampOrigin) AS TimestampOrigin,
SUM(CASE WHEN Number < 1 THEN 1 ELSE 0 END) AS Less1,
SUM(CASE WHEN Number >= 0 AND Number < 10 THEN 1 ELSE 0 END) AS Less10,
SUM(CASE WHEN Number >= 10 AND Number < 25 THEN 1 ELSE 0 END) AS Less25
FROM tblData WHERE Number NOT NULL GROUP BY DATE(TimestampOrigin) ORDER BY TimestampOrigin DESC
What I need is for every day the sum for the current up to Timestamp which is current day +17 days. Example for day 2021-02-08, sum of all rows with TimestampOrigin 2021-02-08 up to 2021-02-08 +17 days (column Timestamp).
Don't know if the extra column Timestamp which is noon time of TimestampOrigin +17 days is really required. But the over time query was the reason why I created it at the very beginning of the project.
SELECT DATE(TimestampOrigin) AS TimestampOrigin,
SUM(CASE WHEN Number < 1 THEN 1 ELSE 0 END) AS Less1,
SUM(CASE WHEN Number >= 0 AND Number < 10 THEN 1 ELSE 0 END) AS Less10,
SUM(CASE WHEN Number >= 10 AND Number < 25 THEN 1 ELSE 0 END) AS Less25
FROM tblData WHERE Number NOT NULL AND DATE(TimestampOrigin) >= DATE('2021-02-08') AND DATE(TimestampOrigin) <= DATE('2021-02-08', '+17 day')
Instead of executing the above query hundreds of times for each day and sum, I thought "with recursive" is the right approach". But was not able so far to make it work. Where to add the 17 days?
WITH RECURSIVE cte AS (
SELECT Id, ComputerName, Timestamp, DATE(Timestamp,'+1 day') totime, Number, TimestampOrigin
FROM tblData
UNION ALL
SELECT Id, ComputerName, DATE(Timestamp,'+1 day'), DATE(totime,'+1 day'), Number, TimestampOrigin
FROM cte
WHERE Number NOT NULL AND DATE(Timestamp,'+1 day') < DATE('2021-02-11')
)
SELECT DATE(TimestampOrigin),
SUM(CASE WHEN Number < 1 THEN 1 ELSE 0 END) AS Less1,
SUM(CASE WHEN Number >= 0 AND Number < 10 THEN 1 ELSE 0 END) AS Less10,
SUM(CASE WHEN Number >= 10 AND Number < 25 THEN 1 ELSE 0 END) AS Less25
FROM cte GROUP BY DATE(TimestampOrigin) ORDER BY DATE(TimestampOrigin) DESC
Expected result would be (Like when I would run the above query for each of the 4 days in the test data):
There is no need for a recursive CTE.
Join the distinct TimestampOrigins to the table under your condition and aggregate:
SELECT t1.TimestampOrigin,
SUM(t2.Number < 1) AS Less1,
SUM(t2.Number >= 0 AND t2.Number < 10) AS Less10,
SUM(t2.Number >= 10 AND t2.Number < 25) AS Less25
FROM (SELECT DISTINCT DATE(TimestampOrigin) TimestampOrigin FROM tblData) t1
INNER JOIN tblData t2
ON DATE(t2.TimestampOrigin) BETWEEN t1.TimestampOrigin AND DATE(t1.TimestampOrigin, '+17 days')
GROUP BY t1.TimestampOrigin
ORDER BY t1.TimestampOrigin DESC
See the demo.
Results:
TimestampOrigin
Less1
Less10
Less25
2021-02-10
0
0
1
2021-02-09
0
0
2
2021-02-08
1
2
2
2021-02-07
1
3
2
The result was wrong. I've found that my initial query was wrong. But with the solution from #forpas it worked at the end.
Initial single query
SELECT
SUM(Number < 1) AS Less1,
SUM(Number >= 1 AND Number < 10) AS Less10,
SUM(Number >= 10 AND Number < 25) AS Less25
FROM tblPCHardwareInformation WHERE UniqueInventoryKey IN
(
SELECT UniqueInventoryKey FROM tblPCHardwareInformation WHERE Number NOT NULL AND DATE(Timestamp) BETWEEN DATE('2020-10-09') AND DATE('2020-10-09', '+17 day') GROUP BY ComputerName ORDER BY Timestamp DESC
)
Result:
SELECT t1.TimestampOrigin,
SUM(t2.Number < 1) AS Less1,
SUM(t2.Number >= 1 AND t2.Number < 10) AS Less10,
SUM(t2.Number >= 10 AND t2.Number < 25) AS Less25
FROM (SELECT DISTINCT DATE(TimestampOrigin) TimestampOrigin FROM tblPCHardwareInformation) t1
INNER JOIN tblPCHardwareInformation t2
ON UniqueInventoryKey IN
(
SELECT UniqueInventoryKey FROM tblPCHardwareInformation WHERE Number NOT NULL AND DATE(Timestamp) BETWEEN DATE(t1.TimestampOrigin) AND DATE(t1.TimestampOrigin, '+17 day') GROUP BY ComputerName ORDER BY Timestamp DESC
)
GROUP BY t1.TimestampOrigin
ORDER BY t1.TimestampOrigin DESC

Is it possible to replace sub-queries, used as a scalar value, with CTE?

I want to replace a long sub-query that return a scalar value or does not exist with just a short alias, because I place it 3 times to the UPDATE statement. Sub-query takes the last value in UncoveredLoss, if there is one, and the new UncoveredLoss value is calculated in the updated row depending on the last UncoveredLoss value.
It is a non-correlated query, but it is used in SELECT clause, not in the FROM clause. Maybe I should somehow modify the UPDATE statement in the trigger.
The working code:
CREATE TRIGGER Result
UPDATE OF Win ON Log
BEGIN
UPDATE Log
SET Profit = CASE
WHEN NEW.Win = 0
THEN - Stake
WHEN NEW.Win = 1
THEN Rate * Stake / 100
WHEN NEW.Win = 2
THEN 0
END
WHERE ID = OLD.ID;
UPDATE Log
SET SumProfit = (
SELECT Sum(Profit)
FROM (
SELECT StrategyAccountID
,Profit
FROM Log
WHERE DATE <= NEW.DATE
)
GROUP BY StrategyAccountID
HAVING StrategyAccountID = NEW.StrategyAccountID
)
WHERE ID = NEW.ID;
UPDATE Log
SET UncoveredLoss = CASE
WHEN EXISTS (
SELECT UncoveredLoss
FROM Log
WHERE DATE < NEW.DATE
AND StrategyAccountID = NEW.StrategyAccountID
ORDER BY DATE DESC LIMIT 1
)
AND (
SELECT UncoveredLoss
FROM Log
WHERE DATE < NEW.DATE
AND StrategyAccountID = NEW.StrategyAccountID
ORDER BY DATE DESC LIMIT 1
) + NEW.Profit < 0
THEN (
SELECT UncoveredLoss
FROM Log
WHERE DATE < NEW.DATE
AND StrategyAccountID = NEW.StrategyAccountID
ORDER BY DATE DESC LIMIT 1
) + NEW.Profit
WHEN NOT EXISTS (
SELECT UncoveredLoss
FROM Log
WHERE DATE < NEW.DATE
AND StrategyAccountID = NEW.StrategyAccountID
ORDER BY DATE DESC LIMIT 1
)
AND NEW.Profit < 0
THEN NEW.Profit
ELSE 0
END
WHERE ID = NEW.ID;
END;
The simple replacement of the sub-query using CTE not working:
CREATE TRIGGER Result
UPDATE OF Win ON Log
BEGIN
UPDATE Log
SET Profit = CASE
WHEN NEW.Win = 0
THEN - Stake
WHEN NEW.Win = 1
THEN Rate * Stake / 100
WHEN NEW.Win = 2
THEN 0
END
WHERE ID = OLD.ID;
UPDATE Log
SET SumProfit = (
SELECT Sum(Profit)
FROM (
SELECT StrategyAccountID
,Profit
FROM Log
WHERE DATE <= NEW.DATE
)
GROUP BY StrategyAccountID
HAVING StrategyAccountID = NEW.StrategyAccountID
)
WHERE ID = NEW.ID;
WITH Loss
AS (
SELECT UncoveredLoss
FROM Log
WHERE DATE < NEW.DATE
AND StrategyAccountID = NEW.StrategyAccountID
ORDER BY DATE DESC LIMIT 1
)
UPDATE Log
SET UncoveredLoss = CASE
WHEN EXISTS (Loss)
AND (Loss) + NEW.Profit < 0
THEN (Loss) + NEW.Profit
WHEN NOT EXISTS (Loss)
AND NEW.Profit < 0
THEN NEW.Profit
ELSE 0
END
WHERE ID = NEW.ID;
END;
Error: near "UPDATE": syntax error
It works nicely when I don't replace the sub-query, but when I try to use CTE it fails. I work in sql.el mode in Emacs.
Yeah, that can be cleaned up a lot. Consider something like:
CREATE TRIGGER Result UPDATE OF Win ON Log BEGIN
UPDATE Log
SET SumProfit = (SELECT sum(Profit)
FROM Log
WHERE Date <= NEW.Date AND StrategyAccountID = NEW.StrategyAccountID)
, UncoveredLoss = ifnull((SELECT min(UncoveredLoss + NEW.Profit, 0)
FROM Log
WHERE Date < NEW.Date AND StrategyAccountID = NEW.StrategyAccountID
ORDER BY Date DESC
LIMIT 1), 0)
WHERE ID = NEW.ID;
END;
which I'm pretty sure calculates the same results as yours. (Actual sample table definition and data to work with would be nice)
Also note that in recent Sqlite3 releases (3.25 and later), your SumProfit column can easily be computed on demand instead of taking up space in the table:
SELECT *
, sum(profit) OVER (PARTITION BY StrategyAccountID ORDER BY Date) AS SumProfit
FROM Log;

How to get maximum column values across a row in Teradata sql?

I have a table named cnst_chrctrstc_abc with 10 columns (equ_gender1 - bb_population_flag) each row which contain numeric values (count) .
I want to get maximum 5 values out of each row across those 10 numeric columns.
The query I have looks something like the following ..
SEL
FROM
(
SEL
SUM(CASE WHEN COALESCE(act.equ_gender1,'') = COALESCE(inact.equ_gender1,'') THEN 0 ELSE 1 END ) AS equ_gender1_chg_cnt,
SUM(CASE WHEN COALESCE(act.exp_ex_bmyr1,'') = COALESCE(inact.exp_ex_bmyr1,'') THEN 0 ELSE 1 END ) AS exp_ex_bmyr1_chg_cnt,
SUM(CASE WHEN COALESCE(act.equ_age1,'') = COALESCE(inact.equ_age1,'') THEN 0 ELSE 1 END ) AS equ_age1_chg_cnt,
SUM(CASE WHEN COALESCE(act.maritalstatus1,'') = COALESCE(inact.maritalstatus1,'') THEN 0 ELSE 1 END ) AS maritalstatus1_chg_cnt,
SUM(CASE WHEN COALESCE(act.person_type1,'') = COALESCE(inact.person_type1,'') THEN 0 ELSE 1 END ) AS person_type1_chg_cnt,
SUM(CASE WHEN COALESCE(act.homeowner,'') = COALESCE(inact.homeowner,'') THEN 0 ELSE 1 END ) AS homeowner_chg_cnt,
SUM(CASE WHEN COALESCE(act.dwelling_size,'') = COALESCE(inact.dwelling_size,'') THEN 0 ELSE 1 END ) AS dwelling_size_chg_cnt,
SUM(CASE WHEN COALESCE(act.lengthofresidence,'') = COALESCE(inact.lengthofresidence,'') THEN 0 ELSE 1 END ) AS lengthofresidence_chg_cnt,
SUM(CASE WHEN COALESCE(act.childrenage0_18,'') = COALESCE(inact.childrenage0_18,'') THEN 0 ELSE 1 END ) AS childrenage0_18_chg_cnt,
SUM(CASE WHEN COALESCE(act.bb_population_flag,'') = COALESCE(inact.bb_population_flag,'') THEN 0 ELSE 1 END ) AS bb_population_flag
FROM
(SEL * FROM arc_mdm_Tbls.cnst_chrctrstc_abc WHERE load_id=1024 AND cnst_chrctrstc_end_dt='9999-12-31' (DATE))act
LEFT JOIN
(SEL * FROM arc_mdm_Tbls.cnst_chrctrstc_abc WHERE load_id=1024 AND cnst_chrctrstc_end_dt<'9999-12-31' (DATE)
QUALIFY ROW_NUMBER() OVER (PARTITION BY cnst_mstr_id ORDER BY cnst_chrctrstc_strt_ts DESC)=1
)inact
ON act.cnst_mstr_id = inact.cnst_mstr_id
)X
I know SEL GREATEST would produce the maximum value out of each row . But I want 5 top values and assign a rank to them.
Something like for some row first five columns may hold the top 5 values and for some last five i.e. homeowner to bb_population_flag may hold the top 5 values.
so if the columns and values from cnst_chrctrstc_abc look something like the following
cdi_batch_id | a | b | c | d | e | f | g | h | i |j
1024 |116|105|102|100|117|119|108|104|101|121
so the select query should return me columns j,f,e,a,g having the top 5 values.
And then I would assign a rank to them accordingly .
Should it be done using unpivot or something ?
Thanks in advance.
Yes, you need to unpivot your result.
Before TD14.10 you will need a list of those column names, either as a table
create table ColumnList (col varchar(128));
Insert into ColumnList('equ_gender1' );
Insert into ColumnList('exp_ex_bmyr1' );
Insert into ColumnList('equ_age1' );
Insert into ColumnList('maritalstatus1' );
Insert into ColumnList('person_type1' );
Insert into ColumnList('homeowner' );
Insert into ColumnList('dwelling_size' );
Insert into ColumnList('lengthofresidence' );
Insert into ColumnList('childrenage0_18' );
Insert into ColumnList('bb_population_flag');
or on-thy-fly using a bulky
with ColumnList as
(
select * from (select 'equ_gender1' as Col) as dt union all
select * from (select 'exp_ex_bmyr1' as Col) as dt union all
select * from (select 'equ_age1' as Col) as dt union all
select * from (select 'maritalstatus1' as Col) as dt union all
select * from (select 'person_type1' as Col) as dt union all
select * from (select 'homeowner' as Col) as dt union all
select * from (select 'dwelling_size' as Col) as dt union all
select * from (select 'lengthofresidence' as Col) as dt union all
select * from (select 'childrenage0_18' as Col) as dt union all
select * from (select 'bb_population_flag' as Col) as dt
)
Then you CROSS JOIN to unpivot:
select
col,
case col
when 'equ_gender1' then equ_gender1
when 'exp_ex_bmyr1' then exp_ex_bmyr1
when 'equ_age1' then equ_age1
when 'maritalstatus1' then maritalstatus1
when 'person_type1' then person_type1
when 'homeowner' then homeowner
when 'dwelling_size' then dwelling_size
when 'lengthofresidence' then lengthofresidence
when 'childrenage0_18' then childrenage0_18
when 'bb_population_flag' then bb_population_flag
end as Counts,
rank() over (order by Counts desc) as rnk
FROM
(
your current select
) as dt
cross join ColumnList
qualify rnk <= 5
In TD14.10 you could utilize the TD_UNPIVOT function:
SELECT Col, rank() over (order by Counts desc) as rnk
from TD_UNPIVOT(
ON (
your current select
)
USING
VALUE_COLUMNS('Counts')
UNPIVOT_COLUMN('Col')
COLUMN_LIST('equ_gender1'
,'exp_ex_bmyr1'
,'equ_age1'
,'maritalstatus1'
,'person_type1'
,'homeowner'
,'dwelling_size'
,'lengthofresidence'
,'childrenage0_18'
,'bb_population_flag')
) dt
qualify rnk <= 5;
Edit:
Additionally you might replace your LEFT JOIN with a single OLAP-function. Depending on the number of rows per cnst_mstr_id this might be more efficient as you need a ROW_NUMBER anyway:
SEL
SUM(CASE WHEN COALESCE(equ_gender1,'') = COALESCE(last_equ_gender1,'') THEN 0 ELSE 1 END ) AS equ_gender1_chg_cnt,
...
FROM
( SELECT
min(equ_gender1) OVER (PARTITION BY cnst_mstr_id ORDER BY cnst_chrctrstc_strt_ts DESC rows between 1 following and 1 following) as equ_gender1,
...
FROM arc_mdm_Tbls.cnst_chrctrstc_abc
WHERE load_id=1024
qualify cnst_chrctrstc_end_dt= date '9999-12-31'
)act

SQL Server 2012 query to compute calculations

I am building a query within SQL Server that is calculating scores we receive for our surveys. We have a column called overall_score, where the user inputs a number from 1-5 as a rating. I am trying to create a stored procedure that will calculate ratings based off the scores.
Score rating = (Total count of scores 4 and 5)/(Total number of responses) * 100
I have three separate select statements that create results I need, but when I go to combine them together my output is 0.
Can someone please guide me on what I am doing wrong here?
Separate SQL Statements:
SELECT count(overall_score) FROM Layer1_DataMerge WHERE overall_score = 4;
SELECT count(overall_score) FROM Layer1_DataMerge WHERE overall_score = 5;
SELECT count(overall_score) FROM Layer1_DataMerge;
Combined together:
SELECT distinct
(
(
(SELECT count(overall_score) FROM Layer1_DataMerge WHERE Overall_Score = 4) +
(SELECT count(overall_score) FROM Layer1_DataMerge WHERE overall_score = 5)
) / (SELECT count(overall_score) FROM Layer1_DataMerge)
) AS CSAT
FROM Layer1_DataMerge;
Well the reason you're getting zero is because you're doing integer division. With integer division 1/3 = 0. You need to convert to floating-point arithmetic, plus you can do it all in one query:
SELECT 100.0 *
(SUM(CASE WHEN overall_score = 4 THEN 1 ELSE 0 END) +
SUM(CASE WHEN overall_score = 5 THEN 1 ELSE 0 END)) /
COUNT(overall_score)
or
SELECT 100.0 *
SUM(CASE WHEN overall_score IN (4,5) THEN 1 ELSE 0 END) /
COUNT(overall_score)
To only show 2 decimals you can either cast to a numeric type with 2 decimals:
SELECT CAST(
100.0 *
SUM(CASE WHEN overall_score IN (4,5) THEN 1 ELSE 0 END) /
COUNT(overall_score)
AS NUMERIC(5,2))
Or use STR to convert to a string:
SELECT STR(
100.0 *
SUM(CASE WHEN overall_score IN (4,5) THEN 1 ELSE 0 END) /
COUNT(overall_score)
,5,2)

Resources