I have a query (portion of it) like this below, when my GridView is loaded with this query, those rows that has got no value for IssCount and UsedCount will be blank. How can I set a default 0 value for these columns for such records?
SELECT
CASE
WHEN #SortByTypeCode = 1 THEN ROW_NUMBER() OVER(ORDER BY vt.Code)
WHEN #SortByTypeName = 1 THEN ROW_NUMBER() OVER(ORDER BY vt.Name)
WHEN #SortByTypeIssued = 1 THEN ROW_NUMBER() OVER(ORDER BY count(X.IssCount))
WHEN #SortByTypeUsed = 1 THEN ROW_NUMBER() OVER(ORDER BY count(Y.UsedCount ))
ELSE ROW_NUMBER() OVER(ORDER BY vt.AutoID)
END AS RowNum
,vt.AutoID
,vt.Code
,X.IssCount as Issued
,Y.UsedCount as Used
INTO #tmp_Results --Dont Change This
FROM VoucherType vt
LEFT JOIN (
SELECT VoucherType_AutoID,COUNT(VoucherNo) IssCount
FROM Voucher
WHERE VoidedBy IS NULL AND VoidedOn IS NULL
GROUP BY VoucherType_AutoID
) X ON vt.AutoID = X.VoucherType_AutoID
LEFT JOIN (
SELECT V.VoucherType_AutoID, COUNT(VUsed.AutoID) UsedCount
FROM voucherUsedLog VUsed
INNER JOIN Voucher V ON VUsed.Voucher_AutoID = V.AutoID
WHERE VUsed.VoidedBy IS NULL AND VUsed.VoidedOn IS NULL
GROUP BY V.VoucherType_AutoID
) Y
ON vt.AutoID = Y.VoucherType_AutoID
You can just wrap a COALESCE around X.IssCount and Y.UsedCount to make them 0, like so:
,COALESCE(X.IssCount,0) as Issued
,COALESCE(Y.UsedCount,0) as Used
Try this way..
ISNULL(X.IssCount,0) as Issued
,ISNULL(Y.UsedCount,0) as Used
Related
I need Only one unique result from tableB.Field to tableA.Field
I am using sdo operator sdo_nn, this is the code:
UPDATE table1 t1
SET t1.fieldA = (SELECT T2.fieldB,SDO_NN_DISTANCE(1) distance
FROM table1 T1, table2 T2
WHERE
(sdo_nn(t1.geometry,t2.geometry,'SDO_NUM_RES=1',1)= 'TRUE')
ORDER BY DIST
)
WHERE EXISTS(
SELECT 1
FROM table2 t2
WHERE sdo_nn(t1.geometry, t2.geometry,'SDO_NUM_RES=1',1)='TRUE'
AND(t2.cell_name = 'string1' or t2.cell_name = string2')AND t1.fieldA = NULL
);
In the select sentence of the subquery i get an error because i only use one field(t1.fieldA), but in the sentence i use the operator SDO_NN_DISTANCE(1) and the sql developer count this operator like another field. What is the correct way to write this sentence? I only use sql because i need to insert this code in vba
Thanks!!!
Obviously, you can't (simplified)
set t1.fieldA = (t2.fieldB, distance) --> you want to put two values into a single column
Therefore, get fieldB alone from the subquery which uses analytic function (row_number) to "sort" rows by sdo_nn_distance(1) desc; then get the first row's fieldB value.
Something like this (I hope I set the parenthesis right):
UPDATE table1 t1
SET t1.fieldA =
(SELECT x.fieldB --> only fieldB
FROM (SELECT T2.fieldB, --> from your subquery
SDO_NN_DISTANCE (1) distance,
ROW_NUMBER ()
OVER (ORDER BY sdo_nn_distance (1) DESC) rn
FROM table1 T1, table2 T2
WHERE (sdo_nn (t1.geometry,
t2.geometry,
'SDO_NUM_RES=1',
1) = 'TRUE')) x
WHERE rn = 1) --> where RN = 1
WHERE EXISTS
(SELECT 1
FROM table2 t2
WHERE sdo_nn (t1.geometry,
t2.geometry,
'SDO_NUM_RES=1',
1) = 'TRUE'
AND ( t2.cell_name = 'string1'
OR t2.cell_name = 'string2')
AND t1.fieldA IS NULL);
i have the following query and the problem is in the Case statement. It s being used in a Join condition. for some reason is bringing up both alternatives from the case
here s the code
SELECT C.GREGORIAN_MONTH_ID
,C.BUSINESS_PARTY_ID
,C.TOTAL_MONTO
,C.Capitas_Puntuales
,C.CUIT
,nb_apellido
,nb_oficial_actual
,nb_cne_obe
,nb_nodo
,nb_territorio
,cd_area_negocio
FROM (SELECT gregorian_month_id
,business_party_id
,Case when BUSINESS_PARTY_ID in (88888,200) then '9999999999999' else business_party_ident_num end CUIT
,SUM(amt_accum) Total_Monto
,count(*) Capitas_Puntuales
FROM dbsreg.A127932_PARTY_MAIN_PAYROLL_HISTORY
where gregorian_month_id= 201806
group by 1,2,3
) C
LEFT JOIN
(select NU_CUIT, nb_apellido,nb_oficial_actual, nb_cne_obe, nb_nodo, nb_territorio,cd_area_negocio
,(fh_corte/100 + 190000) gregorian_month_id
from dbsreg.a119527_base_info_gerencial
) G
on C.CUIT = G.NU_CUIT
and (case
when C.gregorian_month_id in (G.gregorian_month_id) then C.gregorian_month_id
else C.gregorian_month_id -1
END) = G.gregorian_month_id
ORDER BY C.BUSINESS_PARTY_ID
anyone can tell what s going on there?
You final query returns C.BUSINESS_PARTY_ID which is not transformed by Case. Your case statement also draws on BUSINESS_PARTY_ID. Did you mean to have C.CUIT instead of C.BUSINESS_PARTY_ID in your outer select statement?
long story short, i moved the case withing to a where statement from table C and added a userdefined value for the gregorian:
SELECT C.GREGORIAN_MONTH_ID
,C.BUSINESS_PARTY_ID
,C.TOTAL_MONTO
,C.Capitas_Puntuales
,C.CUIT
,nb_apellido
,nb_oficial_actual
,nb_cne_obe
,nb_nodo
,nb_territorio
,cd_area_negocio
FROM (SELECT gregorian_month_id
,business_party_id
,Case when BUSINESS_PARTY_ID in (88888,200) then '9999999999999' else business_party_ident_num end CUIT
,SUM(amt_accum) Total_Monto
,count(*) Capitas_Puntuales
FROM dbsreg.A127932_PARTY_MAIN_PAYROLL_HISTORY
where gregorian_month_id= ?FECHA_BASE
group by 1,2,3
) C
LEFT JOIN
(select NU_CUIT, nb_apellido,nb_oficial_actual, nb_cne_obe, nb_nodo, nb_territorio,cd_area_negocio
,(fh_corte/100 + 190000) gregorian_month_id
from dbsreg.a119527_base_info_gerencial
where gregorian_month_id = (Case when ?FECHA_BASE = (gregorian_month_id) then gregorian_month_id else gregorian_month_id-1 end )
) G
on C.CUIT = G.NU_CUIT
ORDER BY C.BUSINESS_PARTY_ID
I have a oracle query
select id from (
select ID, ROW_NUMBER() over (partition by LATEST_RECEIPT order by ID) rownumber
from Table
where LATEST_RECEIPT in
(
select LATEST_RECEIPT from Table
group by LATEST_RECEIPT
having COUNT(1) > 1
)
) t
where rownumber <> 1;
The data type of LATEST_RECEIPT was earlier varchar2(4000) and this query worked fine. Since the length of the column needs to be extended i modified it to CLOB, after which this fails. Could anyone help me fix this issue or provide a work around?
You can change your inner query to look for other rows with the same last_receipt value but a different ID (assuming ID is unique); if another row exists then that is equivalent to your count returning greater than one. But you can't simply test two CLOB values for equality, you need to use dbms_lob.compare:
select ID
from your_table t1
where exists (
select null from your_table t2
where dbms_lob.compare(t2.LATEST_RECEIPT, t1.LATEST_RECEIPT) = 0
and t2.ID != t1.ID
-- or if ID isn't unique: and t2.ROWID != t1.ROWID
);
Applying the row number filter is tricker, as you also can't use a CLOB in the analytic partition by clause. As André Schild suggested, you can use a hash; here passing the integer value 3, which is the equivalent of dbms_crypto.hash_sh1 (though in theory that could change in a future release!):
select id from (
select ID, ROW_NUMBER() over (partition by dbms_crypto.hash(LATEST_RECEIPT, 3)
order by ID) rownumber
from your_table t1
where exists (
select null from your_table t2
where dbms_lob.compare(t2.LATEST_RECEIPT, t1.LATEST_RECEIPT) = 0
and t2.ID != t1.ID
-- or if ID isn't unique: and t2.ROWID != t1.ROWID
)
)
where rownumber > 1;
It is of course possible to get a hash collision, and if that happened - you had two latest_receipt values which both appeared more than once and both hashed to the same value - then you could get too many rows back. That seems pretty unlikely, but it's something to consider.
So rather than ordering you can only look for rows which have the same lastest_receipt and a lower ID:
select ID
from your_table t1
where exists (
select null from your_table t2
where dbms_lob.compare(t2.LATEST_RECEIPT, t1.LATEST_RECEIPT) = 0
and t2.ID < t1.ID
);
Again that assumes ID is unique. If it isn't then you could still use rowid instead, but you would have less control over which rows were found - the lowest rowid isn't necessarily the lowest ID. Presumably you're using this to dine rows to delete. If you actually don't mind which row you keep and which you delete then you could still do:
and t2.ROWID < t1.ROWID
But since you are currently ordering that probably isn't acceptable, and hashing might be preferable, despite the small risk.
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
How to achieve the result set in sql query
You could work along
WITH
T1 AS (
SELECT
val,
ROW_NUMBER() OVER (PARTITION BY NULL ORDER BY id) rn
FROM Table1
),
T2 AS (
SELECT
val,
ROW_NUMBER() OVER (PARTITION BY NULL ORDER BY id) rn
FROM Table2
),
T3 AS (
SELECT
val,
ROW_NUMBER() OVER (PARTITION BY NULL ORDER BY id) rn
FROM Table3
)
SELECT
T1.val column1
, T2.val column2
, T3.val column3
FROM T1
JOIN T2
ON T1.rn = T2.rn
JOIN T3
ON T2.rn = T3.rn
ORDER BY T1.rn
;
You'd need to
put the statements, which are now going into the UNION into "T1" through "T3", and
move your current sort orders to the ROW_NUMBER analytic functions respectively.
… and should be done: SQL Fiddle
Please comment, if and as further detail is required.