Convert INNER JOIN to LEFT JOIN - Sql - sql

i have a query which returns ~ 97k records because i am using an inner join. Now i want to use left join to show also the null records on the right table(should be about 300k records). This is the actual query(INNER JOIN):
select artnr as "Article number", ardbez1 as "Article description ", arpadrnr as "Supplier code", cd.ADPPHYSLAND as "Country of this supplier code", p.adrnr as "Parent supplier code", p.adrkname as "Name of parent", pd.ADPPHYSLAND as "Country of parent ", arppreis as "Price", arpwae as "Unit", arzwert as "COO", atatarnr as "HS Code"
from mic_ccs_artikel, mic_ccs_artikeldetail, mic_ccs_artikelpreis, mic_dna_adressen c, mic_dna_adrdetail cd, mic_dna_adressen p, mic_dna_adrrelation, mic_dna_adrdetail pd, mic_ccs_artikelzoll, mic_ccs_artikeltarif
where artsid = ardartsid
and arddatstart <= sysdate
and nvl(arddatend, '01.01.4000') >= sysdate
and artsid = arpartsid
and ARPPREISART = 'VP'
and arpdatstart <= sysdate
and nvl(arpdatend, '01.01.4000') >= sysdate
and c.adrsid = cd.adpadrsid
and arpadrnr = c.adrnr
and cd.adpdatvon <= sysdate
and nvl(cd.adpdatbis, '01.01.4000') >= sysdate
and c.adrmandant = 'S1'
and c.adrwerk = 'V1'
and p.adrmandant = 'S1'
and p.adrwerk = 'V1'
and p.adrsid = arlrelsid1
and c.adrsid = arlrelsid2
and p.adrsid = pd.adpadrsid
and pd.adpdatvon <= sysdate
and nvl(pd.adpdatbis, '01.01.4000') >= sysdate
and artsid = arzartsid
and arztyp = 'URLD'
and arzadrnr = c.adrnr
and arzdatstart <= sysdate
and nvl(arzdatend, '01.01.4000') >= sysdate
and artsid = ataartsid
and ATAREGION = 'SE'
and atatarart='EXPORT'
and atadatstart <= sysdate
and nvl(atadatend, '01.01.4000') >= sysdate
;
Then i tried to "convert" it to LEFT JOIN, but it's always showing the same result:
select artnr as "Article number", ardbez1 as "Article description ", arpadrnr as "Supplier code", cd.ADPPHYSLAND as "Country of this supplier code", p.adrnr as "Parent supplier code", p.adrkname as "Name of parent", pd.ADPPHYSLAND as "Country of parent ", arppreis as "Price", arpwae as "Unit", arzwert as "COO", atatarnr as "HS Code"
from mic_ccs_artikel, mic_ccs_artikeldetail, mic_ccs_artikelpreis, mic_dna_adressen c, mic_dna_adrdetail cd, mic_dna_adressen p, mic_dna_adrrelation, mic_dna_adrdetail pd, mic_ccs_artikelzoll, mic_ccs_artikeltarif
where artsid = ardartsid(+)
and arddatstart <= sysdate
and nvl(arddatend, '01.01.4000') >= sysdate
and artsid = arpartsid(+)
and ARPPREISART = 'VP'
and arpdatstart <= sysdate
and nvl(arpdatend, '01.01.4000') >= sysdate
and c.adrsid = cd.adpadrsid(+)
and arpadrnr = c.adrnr
and cd.adpdatvon <= sysdate
and nvl(cd.adpdatbis, '01.01.4000') >= sysdate
and c.adrmandant = 'S1'
and c.adrwerk = 'V1'
and p.adrmandant = 'S1'
and p.adrwerk = 'V1'
and p.adrsid = arlrelsid1(+)
and c.adrsid = arlrelsid2
and p.adrsid = pd.adpadrsid
and pd.adpdatvon <= sysdate
and nvl(pd.adpdatbis, '01.01.4000') >= sysdate
and artsid = arzartsid(+)
and arztyp = 'URLD'
and arzadrnr = c.adrnr
and arzdatstart <= sysdate
and nvl(arzdatend, '01.01.4000') >= sysdate
and artsid = ataartsid(+)
and ATAREGION = 'SE'
and atatarart='EXPORT'
and atadatstart <= sysdate
and nvl(atadatend, '01.01.4000') >= sysdate
;
Why is it always showing the same result?

Echoing the sentiments in the comments, using a left join and a where clause can result in some unexpected behavior. See my answer here for more details as to why that happens. Basically, you should switch to using ANSI syntax and alias your tables. In your case, that would look something like
select * -- select whichever fields you want here
from mic_ccs_artikel a -- only one table in the from clause
left join mic_ccs_artikeldetail b on b.someID = a.someID -- join conditions here
left join mic_ccs_artikelpreis c
on c.someID = a.someID -- join conidition
and c.someField = 'Some Property' -- filtering here
...
The secondary join conditions removes the risk of throwing out those records in the where clause. Again, see my other answer for more details on that.

Related

ORA-01476: Divisor is equal to zero

I have this query that I've been given to fix and I cannot understand why its causing error. I reviewed similar topics involving the max function and the null function but I can't seem to make them work without throwing another error.
select case when count(trlr_num) > 0 then 'Inbounds Need Closed'
else 'All Good'
end as "Inbounds To Be Closed"
from (select t.trlr_num,
r.invnum "Invoice",
to_char(nvl(max(rl.init_rcv_dte), sysdate), 'MM/DD/YY HH:MI AM') as "Begin receive date",
round(sum(rl.idnqty) / sum(rl.expqty) *100, 1) as "% Received%"
from trlr t
join rcvinv r
on t.trlr_num = r.trknum
join rcvlin rl
on r.trknum = rl.trknum
and r.supnum = rl.supnum
and r.invnum = rl.invnum
and r.wh_id = rl.wh_id
join rcvtrk rt
on r.trknum = rt.trknum
and t.trlr_id = rt.trlr_id
and r.wh_id = rt.wh_id
where t.yard_loc_wh_id = 'US_3218'
and rt.rcvtrk_stat <> 'C'
and r.invtyp not in ('PKG', 'XFR')
and (rl.rcvsts <> 'QI' or (rl.rcvsts = 'QI' and t.trlr_seal1 is not null and t.trlr_seal2 is not null))
group by t.trlr_num,
r.invnum
having sum(rl.idnqty) / sum(rl.expqty) = 1
and nvl(max(rl.init_rcv_dte), sysdate) < sysdate -2)

Teradata SQL Update Table "Query Error 3802 Database 'oo' does not exist"

I need help with the following query code. Currently it is giving me the 3802 query error "Database does not exist". Well I did my "from" selection query as 'oo', so that definitely exists. This worked yesterday with some minor changes to the "from" part of the query. The assistance is appreciated.
UPDATE snd_bqa.open_order_all_test
FROM (
SELECT
CASE WHEN m.order_status_desc = 'Completed' AND NVL(c.supptype, 'NULL') <> 'CAN'
THEN 'YES'
ELSE 'NO'
END AS "Order Complete",
CASE WHEN m.order_status_desc = 'Completed' AND c.supptype = 'CAN'
THEN 'YES'
ELSE 'NO'
END AS "Order Cancelled",
CASE WHEN pih.effective_start_date IS NOT NULL AND pih.product_instance_status_code = 3
THEN 'YES'
ELSE 'NO'
END AS "Service Active in PB",
c.ordernumber,
c1.order_requested_due_date,
c.creationdate AS "Order Creation Date",
c.ordersubmitdate AS "Order Submit Date",
c.lastupdateddate,
c.supptype,
m.order_status_desc,
m.phase_stage,
cus.sub_nasp_id,
cus.gch_id,
b.work_order_no,
b.itemcode,
b.instance_id,
COALESCE(b.specific_date, b.standard_date) AS "Service Req Due Date",
m.milestone,
m.milestone_desc,
cus.custlegalname,
a.account_number,
vle.vle_id,
vle.currency_cd,
cus.duns_number,
a.cle_vle_id,
CURRENT_TIMESTAMP(2) AS "Originally Loaded",
CURRENT_TIMESTAMP(2) AS "Last Upd",
CAST((CASE WHEN m.order_status_desc = 'Completed' AND NVL(c.supptype, 'NULL') <> 'CAN'
THEN c.lastupdateddate
ELSE NULL
END) AS TIMESTAMP(2)) "Order Completed Date",
CAST((CASE WHEN m.order_status_desc = 'Completed' AND c.supptype = 'CAN'
THEN c.lastupdateddate
ELSE NULL
end) AS TIMESTAMP(2)) "Order Cancelled Date",
pih.last_modified AS "Service Last Modified Date",
pih.effective_start_date AS "Service Effective Date"
FROM (
SELECT *
FROM edw_stg_ord_cw_vw.cwpc_basketitem
WHERE itemcode LIKE 'PR%'
AND (instance_id, lastupdateddate) IN (
SELECT instance_id, MAX(lastupdateddate)
FROM edw_stg_ord_cw_vw.cwpc_basketitem
GROUP BY instance_id
)) AS b
INNER JOIN edw_stg_ord_cw_vw.cworderinstance AS c
ON c.basket_id = b.basketid
AND c.isactive = 1
AND c.request_type = 'ORD'
LEFT JOIN (
SELECT c.ordernumber,
MAX(COALESCE(b.specific_date, b.standard_date)) order_requested_due_date
FROM edw_stg_ord_cw_vw.cworderinstance AS c
INNER JOIN edw_stg_ord_cw_vw.cwpc_basketitem AS b
ON b.basketid = c.basket_id
AND c.request_type = 'ORD'
AND c.isactive = 1
GROUP BY c.ordernumber
) AS c1
ON c1.ordernumber = c.ordernumber
LEFT JOIN edw_stg_ord_cw_vw.uno_customer AS cus
ON cus.cworderid = c.cwdocid
AND cus.oi_customer_id = c.ordering_customer_id
LEFT JOIN edw_stg_ord_cw_vw.uno_milestone AS m
ON m.milestone_id = c.milestone_id
LEFT JOIN edw_stg_ord_cw_vw.uno_account AS a
ON a.cworderid = c.cwdocid
AND b.account_id = a.oi_account_id
LEFT JOIN edw_stg_ord_cw_vw.uno_cle_vle AS vle
ON vle.cle_vle_id = a.cle_vle_id
AND c.cwdocid = vle.cworderid
INNER JOIN snd_bqa.open_order_all_test tst
ON tst."Service Instance ID" = b.instance_id
AND tst."Milestone" <> m.milestone
LEFT JOIN edw_pb_stg_vw.product_instance_history AS pih
ON pih.general_5 = tst."Service Instance ID"
WHERE cus.sub_nasp_id NOT IN ('19HNYO', '23MAXA', '19HNYR', '10INTD')
AND COALESCE(b.specific_date, b.standard_date, c1.order_requested_due_date) BETWEEN CURRENT_DATE - 60 AND CURRENT_DATE - 30
) oo
SET "Order Complete" = oo."Order Complete",
"Order Cancelled" = oo."Order Cancelled",
"Service Active in PB" = oo."Service Active in PB",
"Service Order Number" = oo.ordernumber,
"Order Requested Due Date" = oo.order_requested_due_date,
"Order Last Updated" = oo.lastupdateddate,
"Order Creation Date" = oo."Order Creation Date",
"Order Submit Date" = oo."Order Submit Date",
"Order Supp Type" = oo.c.supptype,
"Order Status" = oo.order_status_desc,
"Phase Stage" = oo.phase_stage,
"Milestone" = oo.milestone,
"Milestone Description" = oo.milestone_desc,
"NASP ID" = oo.sub_nasp_id,
"GCH ID" = oo.gch_id,
"Work Order Numbers" = oo.work_order_no,
"Product Code" = oo.itemcode,
"Service Requested Due Date" = oo."Service Req Due Date",
"Customer Name" = oo.custlegalname,
"Account Number" = oo.account_number,
"VLE ID" = oo.vle_id,
"Currency Code" = oo.currency_cd,
"DUNs Number" = oo.duns_number,
"CLE VLE ID" = oo.cle_vle_id,
"Last Record Update" = oo."Last Upd",
"Order Completed Date" = oo."Order Completed Date",
"Order Cancelled Date" = oo."Order Cancelled Date",
"Service Last Modified Date" = oo."Service Last Modified Date",
"Service Effective Date" = oo."Service Effective Date"
WHERE open_order_all_test."Service Instance ID" = oo.instance_id
;
I found the issue. I had oo.c.supptype, when it should have just been oo.supptype
This caused Teradata to think 'oo' was referring to a database. case closed.

Calculating (dividing) two summed fields in SQL Query

I have this query:
Select FMUM.DimSubscriptionKey, sum(FMUM.TotalUnits) as TotalUnits, sum(FMUM.AI_NormalizedUsage) as AI_NormalizedUsage
from [AI_DataMart].[AzureViews].[v_FactMeteredUsageMonthly] as FMUM
join [AI_DataMart].[AzureViews].[v_DimServiceExtended] as SE on(FMUM.DimServiceKey = SE.DimServiceKey)
join [AI_DataMart].[AzureViews].[v_DimAccount] as A on(FMUM.DimAccountKey = A.DimAccountKey)
Join [AI_DataMart].[AzureViews].[v_DimSubscription] as SU on(FMUM.DimSubscriptionKey = SU.DimSubscriptionKey)
where
FMUM.DimDateKey >= '20150201'And FMUM.DimDateKey <= '20150331'
And SE.Workload = 'SQLDB'
And SE.ResourceName != 'SQL Reporting Hours'
And (SU.AI_BillingType = 'EA' or SU.AI_BillingType = 'Direct')
AND SU.IsFraudIdentified = 0
AND SU.AI_IsTest = 0
AND SU.DimBillingSystemKey = 1
AND FMUM.DimSubscriptionKey = '4707785'
group by FMUM.DimSubscriptionKey
Which Returns this result:
DimSubscriptionKey TotalUnits AI_NormalizedUsage
4707785 24.77043700 21.08775630
What I need to get and can't get to work is a 4th Column Which would be (AI_NormaliedUsage / TotalUnits)
But when I add it to the query:
Select FMUM.DimSubscriptionKey, sum(FMUM.TotalUnits) as TotalUnits, sum(FMUM.AI_NormalizedUsage) as AI_NormalizedUsage, (AI_NormalizedUsage / TotalUnits)
from [AI_DataMart].[AzureViews].[v_FactMeteredUsageMonthly] as FMUM
join [AI_DataMart].[AzureViews].[v_DimServiceExtended] as SE on(FMUM.DimServiceKey = SE.DimServiceKey)
join [AI_DataMart].[AzureViews].[v_DimAccount] as A on(FMUM.DimAccountKey = A.DimAccountKey)
Join [AI_DataMart].[AzureViews].[v_DimSubscription] as SU on(FMUM.DimSubscriptionKey = SU.DimSubscriptionKey)
where
FMUM.DimDateKey >= '20150201'And FMUM.DimDateKey <= '20150331'
And SE.Workload = 'SQLDB'
And SE.ResourceName != 'SQL Reporting Hours'
And (SU.AI_BillingType = 'EA' or SU.AI_BillingType = 'Direct')
AND SU.IsFraudIdentified = 0
AND SU.AI_IsTest = 0
AND SU.DimBillingSystemKey = 1
AND FMUM.DimSubscriptionKey = '4707785'
group by FMUM.DimSubscriptionKey, (AI_NormalizedUsage / TotalUnits)
I am not getting expected results:
DimSubscriptionKey TotalUnits AI_NormalizedUsage (No column name)
4707785 1.45831000 0.70567620 0.48389999382847268413
4707785 3.39577900 3.28609533 0.96769999755578911348
4707785 9.49984800 9.19300290 0.96769999898945751553
4707785 3.41661200 3.30625543 0.96769999929754973640
4707785 4.49992800 2.17751515 0.48389999795552284392
4707785 2.49996000 2.41921129 0.96769999919998719979
What I want is
DimSubscriptionKey TotalUnits AI_NormalizedUsge NewCalculatedField<br>
4707785 24.770437 21.0877563 0.851327585
What am I missing? Racking my brain!
if you're referencing derived columns from within the same select statement you can't refer to them by their alias, you need to either duplicate the calculation, or wrap it in another select statement.
Without knowing anything about the underlying tables, this fix should work:
Select FMUM.DimSubscriptionKey, sum(FMUM.TotalUnits) as TotalUnits, sum(FMUM.AI_NormalizedUsage) as AI_NormalizedUsage, sum(FMUM.AI_NormalizedUsage) / sum(FMUM.TotalUnits) NewCalculatedField
from [AI_DataMart].[AzureViews].[v_FactMeteredUsageMonthly] as FMUM
join [AI_DataMart].[AzureViews].[v_DimServiceExtended] as SE on(FMUM.DimServiceKey = SE.DimServiceKey)
join [AI_DataMart].[AzureViews].[v_DimAccount] as A on(FMUM.DimAccountKey = A.DimAccountKey)
Join [AI_DataMart].[AzureViews].[v_DimSubscription] as SU on(FMUM.DimSubscriptionKey = SU.DimSubscriptionKey)
where
FMUM.DimDateKey >= '20150201'And FMUM.DimDateKey <= '20150331'
And SE.Workload = 'SQLDB'
And SE.ResourceName != 'SQL Reporting Hours'
And (SU.AI_BillingType = 'EA' or SU.AI_BillingType = 'Direct')
AND SU.IsFraudIdentified = 0
AND SU.AI_IsTest = 0
AND SU.DimBillingSystemKey = 1
AND FMUM.DimSubscriptionKey = '4707785'
group by FMUM.DimSubscriptionKey
Sorry I can't comment but have you tried this:
Select FMUM.DimSubscriptionKey, sum(FMUM.TotalUnits) as TotalUnits, sum(FMUM.AI_NormalizedUsage) as AI_NormalizedUsage, (sum(FMUM.AI_NormalizedUsage / sum(FMUM.TotalUnits))
Should not need the group by either.

VB.NET LINQ query Where with AndAlso and Or

In VB.NET, if I am doing a LINQ query that looks like this:
From a in entitity.name
Where a.id = id _
AndAlso a.date < currentDate _
AndAlso a.statusId = 1 Or a.statusId = 3
Select
On line 4, will the or clause evaluate to return all entities with a statusId of 3, or will it only return the entities that fit the other criteria and have a statusId of 1 or 3?
If that line were changed to
AndAlso (a.statusId = 1 Or a.statusId = 3)
How would that change the expected results?
In VB.NET, conjunction (And, AndAlso) operators occur before inclusive disjunction (Or, OrElse) operators. See Operator Precedence in Visual Basic.
So as soon as a.statusId = 3 is true, it will return true.
And adding parenthesis
AndAlso (a.statusId = 1 Or a.statusId = 3)
will therefore change the behaviour
from:
return TRUE if (a.id = id AND a.date < currentDate AND a.statusId = 1) OR a.statusId = 3
to:
return TRUE if a.id = id AND a.date < currentDate AND (a.statusId = 1 OR a.statusId = 3)
From a in entitity.name
Where a.id = id _
AndAlso a.date < currentDate _
AndAlso a.statusId = 1 Or a.statusId = 3
Select
is equivalent to having (notice the addition of parentheses below):
From a in entitity.name
Where (a.id = id _
AndAlso a.date < currentDate _
AndAlso a.statusId = 1) Or (a.statusId = 3)
Select
Which would return any results where the id matches, the date is less than currentDate, and the status is 1. It will also return ANY results where the statusId is 3.
Whereas having:
From a in entitity.name
Where a.id = id _
AndAlso a.date < currentDate _
AndAlso (a.statusId = 1 Or a.statusId = 3)
Select
Would then return any results where the id matches, the date is less than currentDate, and the status is 1 or 3.
This is the same type of behavior you would see in SQL, or even in general math. 1 + 2 * 3 does not yield the same result as (1 + 2) * 3. It changes the order of operations/the meaning of the statement completely (at least in this case).

DB2 SQL Select Statement & Group By

I am having trouble getting my query to group correctly. I need to include the TELLERACTIVITY.ENTRY_DATE date column so I can filter by the date later on. However, I do not want it to group by the TELLERACTIVITY.ENTRY_DATE date because it gives me more results than I want.
SELECT DISTINCT ACTIVITYINFO.MEMBER_NBR AS "Member Number"
,ACCOUNT.ACCOUNT_NBR AS "Account Number"
,TELLERACTIVITY.FOCUS_TELLER_ID AS "Teller ID"
,TELLERACTIVITY.ENTRY_DATE AS "Date"
,SUM(( CASE WHEN OPERATOR.BRANCH_NBR = 1 THEN 1
ELSE 0
END )) AS "Branch 1"
,SUM(( CASE WHEN OPERATOR.BRANCH_NBR = 2 THEN 1
ELSE 0
END )) AS "Branch 2"
,SUM(( CASE WHEN OPERATOR.BRANCH_NBR = 3 THEN 1
ELSE 0
END )) AS "Branch 3"
,SUM(( CASE WHEN OPERATOR.BRANCH_NBR = 4 THEN 1
ELSE 0
END )) AS "Branch 4"
FROM TELLERACTIVITY
JOIN OPERATOR
ON TELLERACTIVITY.FOCUS_TELLER_ID = OPERATOR.OPR_NBR
JOIN ACTIVITY
ON TELLERACTIVITY.ACTIVITY_ID = ACTIVITY.ACTIVITY_ID
AND TELLERACTIVITY.FOCUS_TELLER_ID = ACTIVITY.FOCUS_TELLER_ID
AND TELLERACTIVITY.ENTRY_DATE = ACTIVITY.ENTRY_DATE
JOIN ACTIVITYINFO
ON ACTIVITY.ACTIVITY_ID = ACTIVITYINFO.ACTIVITY_ID
JOIN ACCOUNT
ON ACTIVITYINFO.MEMBER_NBR = ACCOUNT.MEMBER_NBR
AND ACTIVITYINFO.ACCOUNT_NBR = ACCOUNT.ACCOUNT_NBR
WHERE TELLERACTIVITY.FOCUS_TELLER_ID < 6000
GROUP BY ACTIVITYINFO.MEMBER_NBR
,ACCOUNT.ACCOUNT_NBR
,OPERATOR.BRANCH_NBR
,TELLERACTIVITY.FOCUS_TELLER_ID
,TELLERACTIVITY.ENTRY_DATE
ORDER BY ACTIVITYINFO.MEMBER_NBR