SQL LEFT() not working as expected when used with GROUP BY and Partition - sql

I have codes that are like 1231231A, 1231231A, 3453454B etc
I need to group them by their number (ignoring the char which is a version) and just get one of each. I also need to drop the last char. My code works in grouping them and returning one of each, but it returns the last char.
Why is it returning the last char when i chop it off?
Expected output is
1231231
3453454
What I'm getting is
1231231A
3453454B
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER(PARTITION BY T.fldProductDescrip
ORDER BY T.fldEffectiveDate DESC) AS rn
FROM (
-- Insert statements for procedure here
SELECT JST.flduid
,JST.fldEffectiveDate
,(CASE
WHEN RIGHT(fldProductDescrip, 1) LIKE '[0-9]'
THEN fldProductDescrip
ELSE LEFT(fldProductDescrip, DATALENGTH(fldProductDescrip) - 1)
END) as fldProductDescrip
,(
CASE
WHEN PE.fldLogoutDateTime IS NULL
THEN PE.fldESigUser
ELSE ''
END
) AS LoggedIn
,(
CASE
WHEN PE.fldLogoutDateTime IS NULL
THEN PE.fldLoginDateTime
ELSE ''
END
) AS LoggedInDateTime
FROM tblJSJobSheetTemplates JST
INNER JOIN tblJSProducts JP ON JST.fldProductUID = JP.fldUID
INNER JOIN tblJSProductEsig PE ON JP.fldProductDescrip = PE.fldProduct
) AS T
WHERE LoggedIn <> ''
)AS G WHERE rn = 1

Related

check for a column if it is null , over a previous term with some conditions

I have lets say two terms term A (previous)and term B (current) , i need to check if pol_cancl_date is null or not in term A , there is a transaction_sequence_number , i need to see if the pol_cncl_date is existing in the greatest A.transaction_sequence_number and if greatest( A.transaction_sequence_number ) is the greated when compared to all B.transaction_sequence_number numbers , if it is then i would want to check for pol_cancl_dates's existence and apply a logic
WITH x AS (
SELECT * FROM (
SELECT
pol_num
,term_start_dt
,term_end_dt,pol_cancel_dt
,trans_seq_num
,future_cancel_dt
,DENSE_RANK() OVER (PARTITION BY pol_num ORDER BY term_end_dt DESC) AS flag
FROM `gcp-ent-datalake-preprod.trns_prop_pol_hs_horison.prop_cost`
--WHERE pol_num IN ('30766675','33896642')
-- pol_num = '33288489'
ORDER BY term_start_dt, term_end_dt DESC
)
)
SELECT
*
,CASE
WHEN prior_pol_cancel_dt IS NOT NULL AND current_trans_seq_num < prior_trans_seq_num THEN prior_pol_cancel_dt
ELSE current_pol_cancel_dt
END apply_cancelled_renewal_dt
FROM (
SELECT
MAX(a.pol_num) AS current_pol_num
,MAX(a.term_start_dt) AS current_term_start_dt
,a.term_end_dt AS current_term_ent_dt
,MAX(a.pol_cancel_dt) AS current_pol_cancel_dt
,MAX(a.trans_seq_num) AS current_trans_seq_num
,MAX(a.future_cancel_dt) AS current_future_cancel_dt
,MAX(a.flag) AS current_flag
,MAX(b.pol_num) AS prior_pol_num
,MAX(b.term_start_dt) AS prior_term_start_dt
,b.term_end_dt AS prior_term_end_dt
,MAX(b.pol_cancel_dt) AS prior_pol_cancel_dt
,MAX(b.trans_seq_num) AS prior_trans_seq_num
,MAX(b.future_cancel_dt) AS prior_future_cancel_dt
,MAX(b.flag) AS prior_flag
FROM (
SELECT * FROM x WHERE flag=1) a
INNER JOIN(
SELECT * FROM x WHERE flag = 2 ) b
ON a.pol_num = b.pol_num AND a.flag = b.flag - 1
WHERE a.pol_cancel_dt IS NOT NULL
AND b.pol_cancel_dt IS NOT NULL
AND greatest(a.trans_seq_num) < b.trans_seq_num
-- AND a.trans_seq_num = GREATEST(a.trans_seq_num)
-- AND b.trans_seq_num = GREATEST(b.trans_seq_num)
GROUP BY a.term_end_dt, b.term_end_dt
)
--WHERE a.term_start_dt < b.term_start_dt
--if prior term GREATEST (trans_sewq num
this logic is still not giving me some results , one thing is that trans_seq_num doesn't necessarily have to be one less

Bizarre Join with comma

I'm looking at someone else's code and find this bizarre join:
SELECT
SUM(
(
intUnitOverheadCost + intUnitLaborCost + intUnitMaterialCost + intUnitSubcontractCost
+ intUnitDutyCost + intUnitFreightCost + intUnitMiscCost
)
*
(
(
CASE
WHEN imtSource = 3
THEN - 1
ELSE 1
END
) * intQuantity
)
)
FROM PartTransactions --imt
INNER JOIN PartTransactionCosts --int
ON imtPartTransactionID = intPartTransactionID
LEFT JOIN Warehouses --imw
ON imtPartWarehouseLocationID = imwWarehouseID
, ProductionProperties --xap <-- weird join
WHERE imtJobID = jmpJobID
AND imtSource IN (2,3)
AND imtReceiptID = ''
AND Upper(imtTableName) <> 'RECEIPTLINES'
AND imtNonInventoryTransaction <= {?CHECKBOXGROUP_4_ShowNonInventory}
AND imtJobType IN (1, 3)
AND imtTransactionDate < DATEADD(d, 1, {?PROMPT_1_TODATE})
AND (
imtNonNettable = 0
OR (
imtNonNettable <> 0
AND ISNULL(imwDoNotIncludeInJobCosts, 0) = 0
)
)
AND intCostType = (
CASE -- Always 1
WHEN xapIMCostingMethod = 1
THEN 1
WHEN xapIMCostingMethod = 2
THEN 2
WHEN xapIMCostingMethod = 3
THEN 3
ELSE 4
END
)
There is only one record in table ProductionProperties and the result of select xapIMCostingMethod from ProductionProperties is always 1.
There are always 4 enumerated results in PartTransactionCosts, but only 1 result is allowed.
ProductionProperties.xapIMCostingMethod is implicitly joining to PartTransactionCosts.intCostType
My specific question is what is really going on with this comma join? It looks like it has to be a cross-join, later filtered in the WHERE clause with one possible result.
Agree with the previous answer. It is a cartesian join but since the rows are 1 it doesn't cause an issue.
I'm thinking if you added rows to ProductionProperties then it would serve as a multiplier for your sum. I did a little experiment to show the issue:
declare #tableMoney table (
unit int,
Product char(5),
xapIMPCostingMethod int,
Cost money
)
declare #tableProdProperties table (
xapIMPCostingMethod int
)
insert #tableMoney (unit, Product, xapIMPCostingMethod, Cost)
values
(1,'bike',1, 2.00),
(1,'car',1, 2.25),
(2,'boat',2, 4.50)
insert #tableProdProperties (xapIMPCostingMethod)
values (1),
(2)
select sum(Cost)
from #tableMoney, #tableProdProperties
I also don't like to use joins where it isn't clear what is joining to what so I always use an alias:
select sum(Cost)
from #tableMoney tbm join #tableProdProperties tpp
on tbm.xapIMPCostingMethod = tpp.xapIMPCostingMethod

Why null value in the table getting error while using lead function

I am getting this error - Error converting data type nvarchar to numeric.
I have data coming from a table and I need only two values from the table where I filter only the number (no alphanumeric so used the isnumeric(covrg_cd)=1). The input data looks like the first picture. The Row 1 will always be null and in other other rows, there may or may not be data. However, because row 1 is always null, the lead function is throwing this error: Error converting data type nvarchar to numeric, but the rate column is always in nvarchar. I am using LEAD function in SQL to get the paybandfrom & paybandto using the Rate from Input table and using row_number() to get the tier value.
Input table
out put must be like this..
I have my query like this
SELECT a.payband , a.[from] as pybdnfrom, (RIGHT('00000000000000000000' + CAST(A.[TO] AS VARCHAR),20)) AS pybndto , a.tier
FROM (SELECT DISTINCT A.RATE as payband, A.RATE as [from], CASE WHEN TIER <> 4 THEN A.[TO] ELSE 100000000.000 END AS [to], ROW_NUMBER() OVER(ORDER BY RATE) AS TIER
FROM(SELECT DISTINCT A.RATE, LEAD(SUM((CONVERT(NUMERIC(20,3), (A.RATE)))-0.010)) OVER(ORDER BY A.RATE) AS [TO], ROW_NUMBER() OVER(ORDER BY A.RATE) AS TIER
FROM (SELECT DISTINCT BN_RATE_KEY02 as RATE, COVRG_CD AS COVERAGE
from #tmppsRateCost
WHERE ISNUMERIC(COVRG_CD) = 1 AND COVRG_CD = '1')A GROUP BY A.RATE)A)A
ORDER BY 1
Any help would be appreciated.
The error is because the '' cannot be parsed as a number. It's not related to the LEAD.
If you want to keep that approach you can modify your query in this way (I just commented the parts I replaced):
SELECT a.payband
,a.[from] AS pybdnfrom
--,(RIGHT('00000000000000000000' + CAST(A.[TO] AS VARCHAR), 20)) AS pybndto
,CASE WHEN payband = '' THEN '' ELSE (RIGHT('00000000000000000000' + CAST(A.[TO] AS VARCHAR), 20)) END AS pybndto
,a.tier
FROM (
SELECT DISTINCT A.RATE AS payband
,A.RATE AS [from]
,CASE
WHEN TIER <> 5
THEN A.[TO]
ELSE 100000000.000
END AS [to]
,ROW_NUMBER() OVER (
ORDER BY RATE
) AS TIER
FROM (
SELECT DISTINCT A.RATE
--,LEAD(SUM((CONVERT(NUMERIC(20, 3), (A.RATE))) - 0.010)) OVER (
,LEAD(SUM((CONVERT(NUMERIC(20, 3), (CASE WHEN A.RATE = '' THEN '0.010' ELSE A.RATE END))) - 0.010)) OVER (
ORDER BY A.RATE
) AS [TO]
,ROW_NUMBER() OVER (
ORDER BY A.RATE
) AS TIER
FROM (
SELECT DISTINCT BN_RATE_KEY02 AS RATE
,COVRG_CD AS COVERAGE
FROM #tmppsRateCost
WHERE ISNUMERIC(COVRG_CD) = 1
AND COVRG_CD = '1'
) A
GROUP BY A.RATE
) A
) A
ORDER BY 1
Anyway I guess you might have a cleaner approach just by removing the empty line in the initial table.
Get rid of ISNUMERIC() and use TRY_CONVERT() insert of CONVERT(). In this condition:
WHERE ISNUMERIC(COVRG_CD) = 1 AND COVRG_CD = '1'
The ISNUMERIC() is just unneeded because you have an exact string comparison.
SELECT a.payband , a.[from] as pybdnfrom,
(RIGHT('00000000000000000000' + CAST(A.[TO] AS VARCHAR),20)) AS pybndto ,
a.tier
FROM (SELECT DISTINCT A.RATE as payband, A.RATE as [from],
CASE WHEN TIER <> 4 THEN A.[TO] ELSE 100000000.000 END AS [to],
ROW_NUMBER() OVER (ORDER BY RATE) AS TIER
FROM (SELECT DISTINCT A.RATE,
LEAD(SUM((TRY_CONVERT(NUMERIC(20,3), (A.RATE)))-0.010)) OVER (ORDER BY A.RATE) AS [TO],
ROW_NUMBER() OVER (ORDER BY A.RATE) AS TIER
FROM (SELECT DISTINCT BN_RATE_KEY02 as RATE, COVRG_CD AS COVERAGE
FROM #tmppsRateCost
WHERE COVRG_CD = '1'
)A
GROUP BY A.RATE
) A
) A
ORDER BY 1;

COALESCE function in OVER statement not working

Can someone please tell me why the COALESCE is working on the first SELECT here and not the other two? I'm still getting NULL values on the second two statements.
(SELECT COALESCE(DEFax, NULL, '') FROM Debtor d WHERE d.DEIsPrimary = 1 AND d.CApKey = c.CApKey) AS FaxNumberOne,
(SELECT COALESCE(DEFax, NULL, '') FROM (SELECT ROW_NUMBER() OVER (ORDER BY DEpKey ASC)
AS rownumber, DEFax FROM Debtor d WHERE d.CApKey = c.CApKey AND d.DEIsPrimary <> 1)
AS foo WHERE rownumber = 1) AS FaxNumberTwo,
(SELECT COALESCE(DEFax, NULL, '') FROM (SELECT ROW_NUMBER() OVER (ORDER BY DEpKey ASC)
AS rownumber, DEFax FROM Debtor d WHERE d.CApKey = c.CApKey AND d.DEIsPrimary <> 1)
AS foo WHERE rownumber = 2) AS FaxNumberThree
Thanks!
Sample data and desired results would really help.
But a scalar subquery is a subquery that returns one column and zero or one rows. If it returns zero rows, then the value is NULL regardless of the expression in the SELECT. In other words, the COALESCE() needs to go outside, something like this:
coalesce( (select . . . . ),
''
)
Including NULL in the coalesce() list is not a good practice. It is unnecessary and misleading -- and always ignored.

Subquery within SubQuery in SQL - DB2

I am having issue when trying to make a the sub query shown in the first filter dynamically based on one of the results returned from the query. Can someone please tell me what I am doing wrong. In the first subquery it worked.
( SELECT
MAX( MAX_DATE - MIN_DATE ) AS NUM_CONS_DAYS
FROM
(
SELECT
MIN(TMP.D_DAT_INDEX_DATE) AS MIN_DATE,
MAX(TMP.D_DAT_INDEX_DATE) AS MAX_DATE,
SUM(INDEX_COUNT) AS SUM_INDEX
FROM
(
SELECT
D_DAT_INDEX_DATE,
INDEX_COUNT,
D_DAT_INDEX_DATE - (DENSE_RANK() OVER(ORDER BY D_DAT_INDEX_DATE)) DAYS AS G
FROM
DWH.MQT_SUMMARY_WATER_READINGS
WHERE
N_COD_METER_CNTX_KEY = 79094
) AS TMP
GROUP BY
TMP.G
ORDER BY
1
) ) AS MAX_NUM_CONS_DAYS
Above is the subquery I am trying to replace 123456 with CTXTKEY or CTXT.N_COD_METER_CNTX_KEY from query. Below is the full code. Please note than in the subquery before "MAX_NUM_CONS_DAYS" it worked. However, it was only one subquery down.
SELECT
N_COD_WM_DWH_KEY,
V_COD_WM_SN_2,
N_COD_SP_ID,
CTXKEY,
V_COD_MIU_SN,
N_COD_POD,
MIU_CAT,
V_COD_SITR_ASSOCIATED,
WO_INST_DATE,
WO_MIU_CAT,
DAYSRECEIVED3,
MAX_NUM_CONS_DAYS,
( CASE WHEN ( DAYSRECEIVED3 = 3 ) THEN 'Y' ELSE 'N' END ) AS GREEN,
( CASE WHEN ( DAYSRECEIVED3 < 3 AND DAYSRECEIVED3 > 0 ) THEN 'Y' ELSE 'N' END ) AS BLUE,
( CASE WHEN ( DAYSRECEIVED3 = 0 AND MAX_NUM_CONS_DAYS >= 5 ) THEN 'Y' ELSE 'N' END ) AS ORANGE,
( CASE WHEN ( DAYSRECEIVED3 = 0 AND MAX_NUM_CONS_DAYS BETWEEN 1 and 4 ) THEN 'Y' ELSE 'N' END ) AS RED
FROM
(
SELECT
WMETER.N_COD_WM_DWH_KEY,
WMETER.V_COD_WM_SN_2,
WMETER.N_COD_SP_ID,
CTXT.N_COD_METER_CNTX_KEY AS CTXKEY,
CTXT.V_COD_MIU_SN,
CTXT.N_COD_POD,
MIU.N_COD_MIU_CATEGORY AS MIU_CAT,
CTXT.V_COD_SITR_ASSOCIATED,
T1.D_DAT_PLAN_INST AS WO_INST_DATE,
T1.N_COD_MIU_CATEGORY AS WO_MIU_CAT,
( SELECT COUNT( DISTINCT D_DAT_INDEX_DATE ) FROM DWH.MQT_SUMMARY_WATER_READINGS WHERE ( N_COD_METER_CNTX_KEY = CTXT.N_COD_METER_CNTX_KEY ) AND D_DAT_INDEX_DATE BETWEEN ( '2013-07-10' ) AND ( '2013-07-12' ) ) AS DAYSRECEIVED3,
( SELECT
MAX( MAX_DATE - MIN_DATE ) AS NUM_CONS_DAYS
FROM
(
SELECT
MIN(TMP.D_DAT_INDEX_DATE) AS MIN_DATE,
MAX(TMP.D_DAT_INDEX_DATE) AS MAX_DATE,
SUM(INDEX_COUNT) AS SUM_INDEX
FROM
(
SELECT
D_DAT_INDEX_DATE,
INDEX_COUNT,
D_DAT_INDEX_DATE - (DENSE_RANK() OVER(ORDER BY D_DAT_INDEX_DATE)) DAYS AS G
FROM
DWH.MQT_SUMMARY_WATER_READINGS
WHERE
N_COD_METER_CNTX_KEY = 79094
) AS TMP
GROUP BY
TMP.G
ORDER BY
1
) ) AS MAX_NUM_CONS_DAYS
FROM DWH.DWH_WATER_METER AS WMETER
LEFT JOIN DWH.DWH_WMETER_CONTEXT AS CTXT
ON WMETER.N_COD_WM_DWH_KEY = CTXT.N_COD_WM_DWH_KEY
LEFT JOIN DWH.DWH_MIU AS MIU
ON CTXT.V_COD_MIU_SN = MIU.V_COD_MIU_SN
LEFT JOIN
( SELECT V_COD_CORR_WAT_METER_SN, D_DAT_PLAN_INST, N_COD_MIU_CATEGORY
FROM DWH.DWH_ORDER_MANAGEMENT_FACT
JOIN DWH.DWH_MIU
ON DWH.DWH_ORDER_MANAGEMENT_FACT.V_COD_MIU_SN = DWH.DWH_MIU.V_COD_MIU_SN
) AS T1
ON WMETER.V_COD_WM_SN_2 = T1.V_COD_CORR_WAT_METER_SN
WHERE
( V_COD_SITR_ASSOCIATED = 'X' )
AND ( ( MIU.N_COD_MIU_CATEGORY <> 4 ) OR ( ( MIU.N_COD_MIU_CATEGORY IS NULL ) AND ( ( T1.N_COD_MIU_CATEGORY <> 4 ) OR ( T1.N_COD_MIU_CATEGORY IS NULL ) ) ) )
)
Error I am getting is:
Error Code: -204, SQL State: 42704
I would say that a good option here would be to use a CTE, or Common Table Expression. You can do something similar to the following:
WITH CTE_X AS(
SELECT VAL_A
,VAL_B
FROM TABLE_A)
,CTE_Y AS(
SELECT VAL_C
,VAL_B
FROM TABLE_B)
SELECT VAL_A
,VAL_B
FROM CTE_X X
JOIN CTE_Y Y
ON X.VAL_A = Y.VAL_C;
While this isn't specific to your example, it does show that CTE's create a sort of temporary "in memory" table that you can access in a subsequent query. This should allow you to issue your inner two subselects as a CTE, and then use the CTE in the "SELECT MAX( MAX_DATE - MIN_DATE ) AS NUM_CONS_DAYS" query.
You cannot reference columns from the outer select in the subselect, no more than 1 level deep anyway. If I correctly understand what you're doing, you'll probably need to join DWH.MQT_SUMMARY_WATER_READINGS and DWH.DWH_WMETER_CONTEXT in the outer select.