How to group when using aggregates in the select statement - sql

I am trying to run the following code, but receive an error because of the last field in the SELECT statement that contains both an aggregate condition and a normal condition
trunc(d.ead_date)- trunc(max(d.pickup_date_ts)) AS diff_ead_cpt_max
The Error is basically saying aggregates not allowed in GROUP BY clause. If I remove the max, then it would work but then I would not get the right results.
SELECT
w1.physical_country origin_country,
a.leg_warehouse_id lm_warehouse_id,
b.leg_warehouse_id fl_warehouse_id,
c.plane_name,
k.leg_ware,
k.last_ds,
trunc(a.ead_date) ead_date,
max(d.pickup_date_ts) max_cpt,
to_char(max(d.pickup_date_ts),'HH24:MI') max_cpt_time,
trunc(max(d.pickup_date_ts)) max_cpt_date,
trunc(d.ead_date)- trunc(max(d.pickup_date_ts)) AS diff_ead_cpt_max
from
final_leg a
inner join dest_leg b
on a.shipment_id = b.shipment_id and a.route_id = b.route_id
inner join sc_execution_eu.o_detailed_routes_v2 d
on a.shipment_id = d.shipment_id and a.route_id = d.route_id and d.leg_sequence_id = 0
left join plane_leg c
on a.shipment_id = c.shipment_id and a.route_id = c.route_id
left join warehouse_attributes w1
on a.route_warehouse_id = w1.warehouse_id
left join warehouse_attributes w2
on b.leg_warehouse_id = w2.warehouse_id
RIGHT JOIN list_legs_ds k
on a.route_warehouse_id = k.leg_ware AND a.leg_warehouse_id = k.last_ds
group by
1,2,3,4,5,6,7,11

GROUP BY the non-aggregated values and use the column names:
SELECT
w1.physical_country origin_country,
a.leg_warehouse_id lm_warehouse_id,
b.leg_warehouse_id fl_warehouse_id,
c.plane_name,
k.leg_ware,
k.last_ds,
trunc(a.ead_date) ead_date,
max(d.pickup_date_ts) max_cpt,
to_char(max(d.pickup_date_ts),'HH24:MI') max_cpt_time,
trunc(max(d.pickup_date_ts)) max_cpt_date,
trunc(d.ead_date)- trunc(max(d.pickup_date_ts)) AS diff_ead_cpt_max
from
final_leg a
inner join dest_leg b
on a.shipment_id = b.shipment_id and a.route_id = b.route_id
inner join sc_execution_eu.o_detailed_routes_v2 d
on a.shipment_id = d.shipment_id and a.route_id = d.route_id and d.leg_sequence_id = 0
left join plane_leg c
on a.shipment_id = c.shipment_id and a.route_id = c.route_id
left join warehouse_attributes w1
on a.route_warehouse_id = w1.warehouse_id
left join warehouse_attributes w2
on b.leg_warehouse_id = w2.warehouse_id
RIGHT JOIN list_legs_ds k
on a.route_warehouse_id = k.leg_ware AND a.leg_warehouse_id = k.last_ds
group by
w1.physical_country origin_country,
a.leg_warehouse_id lm_warehouse_id,
b.leg_warehouse_id fl_warehouse_id,
c.plane_name,
k.leg_ware,
k.last_ds,
trunc(a.ead_date),
trunc(d.ead_date)

You cannot remove max as you already said, since pickup_date_ts,as being a non-aggregated column, not-listed in the GROUP BY list.
Try trunc( max(trunc(d.ead_date) - d.pickup_date_ts)).
Btw, it's not suggested to use column order numbers in the GROUP BY expression, some changes in the SELECT list may have an advers impact on them, rather write columns' names explicitly.

Related

Comparing values in two rows and getting ORA-00918: column ambiguously defined

I am trying to compare values from one column in two different rows using CASE statement. Inner SELECT statements are identical and working OK giving me fields that I need. Then I inner joined them on one of the key fields (KYCID). That's where I get "column ambiguously defined" error. I tried to remove duplicate rows by using DISTINCT - still the same error.
SELECT DISTINCT e.KYCID,
CASE WHEN e.HRAC_FLAG <> f.HRAC_FLAG THEN 'FALSE' ELSE 'TRUE' END AS FLAG_COMPARISON
FROM
(SELECT gt.task_id, gt.work_item_status, gt.work_item_type, gt.component_id, xref.HRAC_FLAG,
xref.case_nbr, xref.task_id, d.kycid, d.core_component_state
FROM kyc_gbl_main.global_task gt
inner join KYC_RGN_NAM_MAIN.CASE_HRAC_XREF xref on gt.component_id = xref.component_id
inner join kyc_rgn_nam_main.account a on xref.accountid = a.accountid
inner join kyc_rgn_nam_main.country_appx_account_xref b on a.accountid = b.accountid
inner join kyc_rgn_nam_main.country_appx c on c.cntry_appx_id = b.cntry_appx_id and
c.country_appx_state = b.country_appx_state
inner join kyc_rgn_nam_main.kyc_main d on d.kycid = c.kycid
where gt.work_item_type = 'HRAC_OVERLAY'
and gt.work_item_status = 'Completed') e
INNER JOIN
(select gt.task_id, gt.work_item_status, gt.work_item_type, gt.component_id, xref.HRAC_FLAG,
xref.case_nbr, xref.task_id, d.kycid, d.core_component_state
from kyc_gbl_main.global_task gt
inner join KYC_RGN_NAM_MAIN.CASE_HRAC_XREF xref on gt.component_id = xref.component_id
inner join kyc_rgn_nam_main.account a on xref.accountid = a.accountid
inner join kyc_rgn_nam_main.country_appx_account_xref b on a.accountid = b.accountid
inner join kyc_rgn_nam_main.country_appx c on c.cntry_appx_id = b.cntry_appx_id and
c.country_appx_state = b.country_appx_state
inner join kyc_rgn_nam_main.kyc_main d on d.kycid = c.kycid
where gt.work_item_type = 'HRAC_OVERLAY'
and gt.work_item_status = 'Completed') f
ON e.KYCID = f.KYCID
WHERE e.core_component_state ='ACTIVE'
AND f.core_component_state = 'IN_PROGRESS';
As determined with process of elimination, you reference the same named column in a SELECT query. To avoid this name collision, consider aliasing those particular columns.
Additionally, to avoid repetition, consider using a CTE via WITH and avoid using table aliases like (a, b, c) or (t1, t2, t3). Finally, move WHERE conditions to ON to filter before combining all data sources.
WITH sub AS (
SELECT gt.task_id AS gt_task_id -- RENAMED TO AVOID COLLISION
, gt.work_item_status
, gt.work_item_type
, gt.component_id
, xref.HRAC_FLAG
, xref.case_nbr
, xref.task_id AS x_ref_task_id -- RENAMED TO AVOID COLLISION
, k.kycid
, k.core_component_state
FROM kyc_gbl_main.global_task gt
INNER JOIN KYC_RGN_NAM_MAIN.CASE_HRAC_XREF xref
ON gt.component_id = xref.component_id
AND gt.work_item_type = 'HRAC_OVERLAY' -- MOVED FROM WHERE
AND gt.work_item_status = 'Completed' -- MOVED FROM WHERE
INNER JOIN kyc_rgn_nam_main.account acc
ON xref.accountid = acc.accountid
INNER JOIN kyc_rgn_nam_main.country_appx_account_xref cax
ON acc.accountid = cax.accountid
INNER JOIN kyc_rgn_nam_main.country_appx ca
ON ca.cntry_appx_id = cax.cntry_appx_id
AND ca.country_appx_state = cax.country_appx_state
INNER JOIN kyc_rgn_nam_main.kyc_main k
ON k.kycid = ca.kycid
)
SELECT DISTINCT
e.KYCID
, CASE
WHEN e.HRAC_FLAG <> f.HRAC_FLAG
THEN 'FALSE'
ELSE 'TRUE'
END AS FLAG_COMPARISON
FROM sub e
INNER JOIN sub f
ON e.KYCID = f.KYCID
AND e.core_component_state = 'ACTIVE' -- MOVED FROM WHERE
AND f.core_component_state = 'IN_PROGRESS' -- MOVED FROM WHERE

SQL Selects combine - Second select to be in Where clause

I have 2 selects. The first one:
select purs.t_orno as purchased
from ttisfc001201 sls
inner join twhinr110201 sfc on sfc.t_orno = sls.t_pdno
inner join twhltc100201 purs on purs.t_clot=sfc.t_clot
left join twhltc220201 items on items.t_clot = sfc.t_clot
left join twhltc210201 cert_num on cert_num.t_item = items.t_item
left join twhltc200201 cert on cert.t_ltft = cert_num.t_ltft
where sls.t_cprj = 'SLS004336' and purs.t_orno like N'PUR%'
and sfc.t_koor = 1 and sfc.t_kost = 5
Is giving me these results:
PUR007833
PUR008544
PUR008698
PUR008963
PUR009048
PUR009304
PUR009611
PUR009912
PUR009913
PUR010006
PUR010110
PUR010400
PUR010465
PUR010539
PUR010664
So basically these are results I must use in the second select in where clause. A field from table in second select must be equal to one of them. To understand me better it should look like this:
select distinct fac.t_isup
from ttfacp200201 fac
inner join ttfacp250201 mid on mid.t_ityp = fac.t_ttyp and mid.t_idoc=fac.t_ninv
where mid.t_orno ='PUR010400' or mid.t_orno='PUR009912'or mid.t_orno='PUR009913'or mid.t_orno='PUR010465'or mid.t_orno='PUR008544'or mid.t_orno='PUR008963'or mid.t_orno='PUR009048'or mid.t_orno='PUR010110'or mid.t_orno='PUR007833'or mid.t_orno='PUR009304'or mid.t_orno='PUR009611'or mid.t_orno='PUR010664'or mid.t_orno='PUR010006'or mid.t_orno='PUR010539'or mid.t_orno='PUR008698'or mid.t_orno='PUR010667'
All these ORs are results from the first select. How I can combine them (the first select to go in second select where clause) so I can get results at once?
You can use the IN clause for your second query
select distinct fac.t_isup
from ttfacp200201 fac
inner join ttfacp250201 mid on mid.t_ityp = fac.t_ttyp and mid.t_idoc=fac.t_ninv
where mid.t_orno IN (
select purs.t_orno
from ttisfc001201 sls
inner join twhinr110201 sfc on sfc.t_orno = sls.t_pdno
inner join twhltc100201 purs on purs.t_clot=sfc.t_clot
left join twhltc220201 items on items.t_clot = sfc.t_clot
left join twhltc210201 cert_num on cert_num.t_item = items.t_item
left join twhltc200201 cert on cert.t_ltft = cert_num.t_ltft
where sls.t_cprj = 'SLS004336' and purs.t_orno like N'PUR%'
and sfc.t_koor = 1 and sfc.t_kost = 5
)
Something like this
;with first_query_cte(purchased) as (
select purs.t_orno
from ttisfc001201 sls
inner join twhinr110201 sfc on sfc.t_orno = sls.t_pdno
inner join twhltc100201 purs on purs.t_clot=sfc.t_clot
left join twhltc220201 items on items.t_clot = sfc.t_clot
left join twhltc210201 cert_num on cert_num.t_item = items.t_item
left join twhltc200201 cert on cert.t_ltft = cert_num.t_ltft
where sls.t_cprj = 'SLS004336' and purs.t_orno like N'PUR%'
and sfc.t_koor = 1 and sfc.t_kost = 5)
select distinct fac.t_isup
from ttfacp200201 fac
inner join ttfacp250201 mid on mid.t_ityp = fac.t_ttyp and mid.t_idoc=fac.t_ninv
inner join first_query_cte fqc on mid.t_orno=fqc.purchased;

Select statement where joins causing records to be excluded

I have the below query with multiple joins.The last 3 joins are required to get the g.fin_id value. This works fine (see results) BUT because some records in the ACCUM_ISS_CHAR_HIST table have e.char9_nme values of NULL, it excludes the records in the results altogether. So it seems as when the e.char9_nme value has a record then it will produce a result, but as soon as it has a Null value then it is excluded. I would still like to see the records even though the g.fin_id for those will then be blank because they have a e.char9_nme value of Null. How can I change the query to accomplish this?
select
a.acct_id,
c.fld3_txt,
b.issue_loc1_cde,
b.instr_id,
a.fld1_nme,
b.issue_cls2_nme,
g.fin_id,
e.char9_nme
from position_dg as a
inner join
infoportal..issue_dg as b on b.INSTR_ID = a.INSTR_ID
inner join
InfoPortal..IVW_ACCT as c on a.acct_id = c.acct_id
inner join
InfoPortal..DW_AcctCharDG as d on a.acct_id = d.acctid
inner join
ACCUM_ISS_CHAR_HIST as e on a.instr_id = e.instr_id
inner join
MD_FINANCIAL_ENTITY as f on e.char9_nme = f.fin_enty_name
inner join md_FINANCIAL_ENTITY_ALTERNATE_IDENTIFIER as g on
f.fin_enty_id = g.fin_enty_id
and b.MAT_EXP_DTE > getdate()
and b.issue_cls1_nme = 'Derivatives'
and a.as_of_tms >= getdate()-1
and b.iss_typ in ('FFX','IRS','EQF')
and d.AcctChrSetId = 'DerivativeRpt'
and d.EndTms IS NULL
and a.acct_id = 'FOGEMBLCR'
and g.id_ctxt_typ = 'LEGAL_ENTITY_IDENTIFIER'
and e.as_of_dte = (
select MAX (as_of_dte)-1
from accum_iss_char_hist
)
I expect the results to show fin_id records for some ond blank fin_id records for some, but at the moment only the ones with a fin_id record is hown and the rest is excluded from the results.
You are looking for a left join.
Join all those tables (last 3 as you said) as left join. For better clarity I have moved conditions of every tables in their ON clause and for base table a made a where clause.
select
a.acct_id,
c.fld3_txt,
b.issue_loc1_cde,
b.instr_id,
a.fld1_nme,
b.issue_cls2_nme,
g.fin_id,
e.char9_nme
from position_dg as a
inner join
infoportal..issue_dg as b on b.INSTR_ID = a.INSTR_ID
and b.MAT_EXP_DTE > getdate()
and b.issue_cls1_nme = 'Derivatives'
and b.iss_typ in ('FFX','IRS','EQF')
inner join
InfoPortal..IVW_ACCT as c on a.acct_id = c.acct_id
inner join
InfoPortal..DW_AcctCharDG as d on a.acct_id = d.acctid
and d.AcctChrSetId = 'DerivativeRpt'
and d.EndTms IS NULL
left join
ACCUM_ISS_CHAR_HIST as e on a.instr_id = e.instr_id
and e.as_of_dte = (
select MAX (as_of_dte)-1
from accum_iss_char_hist
)
left join
MD_FINANCIAL_ENTITY as f on e.char9_nme = f.fin_enty_name
left join
md_FINANCIAL_ENTITY_ALTERNATE_IDENTIFIER as g on f.fin_enty_id = g.fin_enty_id
and g.id_ctxt_typ = 'LEGAL_ENTITY_IDENTIFIER'
Where a.as_of_tms >= getdate()-1
and a.acct_id = 'FOGEMBLCR'

SQL-Get and replace minimum value of a query's field

I have the following query in Postgresql :
SELECT mq.nombre,sa.nombre,COUNT(DISTINCT(ae.numero_serie)),SUM(im.fin-im.inicio),MIN(pz.fecha_inicio)
FROM item_metraje AS im LEFT JOIN articulo_especificado AS ae ON (im.id_articulo_especificado = ae.id)
LEFT JOIN articulo AS a ON (ae.id_articulo = a.id)
LEFT JOIN serie_articulo AS sa ON (a.id_serie_articulo = sa.id)
LEFT JOIN reporte_perforacion AS rp ON (rp.id = im.id_reporte_perforacion)
LEFT JOIN pozo AS pz ON (pz.id=rp.id_pozo) LEFT JOIN proyecto AS p ON (p.id=pz.id_proyecto)
LEFT JOIN maquina_perforacion AS mq ON (mq.id = pz.id_maquina)
WHERE p.id = 2 GROUP BY mq.nombre,sa.nombre
and the result is :
However I want to put the minimum date for the rows that have the same value of the field 'nombre', for example for the value 'JM04' the three rows must have the date 2015-01-25 because it is the minimum value of the three rows.
Excuse me for my English and thanks for all.
You can use Window functions for this purpose. MIN(pz.fecha_inicio) over (partition by mq.nombre).
Therefore the final query is,
SELECT z.nombre1,z.nombre2,z.count,z.sum ,MIN(z.date) over (partition by z.nombre1) from
(SELECT mq.nombre as nombre1 ,sa.nombre as nombre2,COUNT(DISTINCT(ae.numero_serie)) as count,SUM(im.fin-im.inicio) as sum ,pz.fecha_inicio as date
FROM item_metraje AS im LEFT JOIN articulo_especificado AS ae ON (im.id_articulo_especificado = ae.id)
LEFT JOIN articulo AS a ON (ae.id_articulo = a.id)
LEFT JOIN serie_articulo AS sa ON (a.id_serie_articulo = sa.id)
LEFT JOIN reporte_perforacion AS rp ON (rp.id = im.id_reporte_perforacion)
LEFT JOIN pozo AS pz ON (pz.id=rp.id_pozo) LEFT JOIN proyecto AS p ON (p.id=pz.id_proyecto)
LEFT JOIN maquina_perforacion AS mq ON (mq.id = pz.id_maquina)
WHERE p.id = 2 GROUP BY mq.nombre,sa.nombre)z
You can modify this with the help of order by or having clauses inside window function as you want. I tried this with my own data set. Hope this helps.

SQL with left outer join and 3 tables

I would like to add an ADD at the end of my code. Please have a look on my code and thanks for your support:
SELECT Area.org,
Supervisors.NomSup,
Supervisors.PrenomSup,
Employees.NomEmp,
Employees.PrenomEmp,
Employees.NoIdAlcanEmp,
Competencies.CodeCompetencies,
Competencies.CompetencyName,
LinkResultComp.AssNote,
LinkResultComp.AssDate
FROM ((((((
Area INNER JOIN Supervisors ON Area.IdArea = Supervisors.IdArea
)
INNER JOIN Employees ON Supervisors.IdSupervisor = Employees.IdSupervisor
)
INNER JOIN LinkProfilesEmployees ON Employees.IdEmp = LinkProfilesEmployees.IdEmp
)
INNER JOIN Profiles ON Profiles.IdProfiles = LinkProfilesEmployees.IdProfiles
)
INNER JOIN LinkProfComp ON Profiles.IdProfiles = LinkProfComp.IdProfiles
)
INNER JOIN Competencies ON Competencies.IdCompetencies = LinkProfComp.IdCompetencies
)
LEFT OUTER JOIN LinkResultComp ON (Competencies.IdCompetencies = LinkResultComp.IdCompetencies AND ON Competencies.IdCompetencies = LinkResultComp.IdCompetencies)
WHERE Area.org LIKE "*20*" AND Competencies.CodeCompetencies LIKE "khse2010-05"
ORDER BY Supervisors.NomSup, Employees.NomEmp;
Just remove the extra ON that you added
So change this
LEFT OUTER JOIN LinkResultComp
ON (Competencies.IdCompetencies = LinkResultComp.IdCompetencies
AND ON Competencies.IdCompetencies = LinkResultComp.IdCompetencies)
------^^ This one
to this
LEFT OUTER JOIN LinkResultComp
ON (Competencies.IdCompetencies = LinkResultComp.IdCompetencies
AND Competencies.IdCompetencies = LinkResultComp.IdCompetencies)
Of course I assume you meant different fields for the second condition