Performing left join along with where condition - sql

I was using this query to get results,
SELECT *
FROM TRXN_REPORT CNT,
TBL_CUSTINFO CUSTADDINFO,
TBL_DEAL_EVT EVENT,
TBL_MISCADDR CIFMISC
WHERE CNT.INTERNAL_REF_NUM = EVENT.INTERNAL_REF_NUM
AND CNT.BRANCH = EVENT.BRANCH
AND CNT.QFXVERSION = EVENT.QFXVERSION
AND CNT.VALUEDATE = EVENT.VALUEDATE
AND CNT.LIQ_STATUS = 'L'
AND EVENT.EVENTCODE = 'LLIQ' -- Liquidation Event
AND CUSTADDINFO.CUSTOMER_NO = CNT.CUST_NUM
AND CIFMISC.CUSTOMER_NUMBER = CNT.CUST_NUM
AND CUSTADDINFO.REC_STATUS ='O'
AND CIFMISC.REC_STATUS = 'O'
AND MY_PBG_CUSTOMER = 'Y'
AND (BUYCCYCODE = 'USD' OR SELLCCYCODE ='USD')
here this condition
AND CIFMISC.CUSTOMER_NUMBER = CNT.CUST_NUM
Is fetching only those records which are present both in TBL_MISCADDR and TRXN_REPORT table, now as a change of requirment I want to perform left outer join so as to get records which are not there in TBL_MISCADDR table but present in TRXN_BATCHREPORT_WRK. How to perform this along with maintaining all the where conditions.

You have to you specify the condition for the join in the ON clause of the JOIN. So, your current conditions in the WHERE clause should be separated into the conditions for joining the tables (and these moved to ON clause), and the rest for selecting the lines - and these should be left in the WHERE clause. Example (don't know if I have it correct according to your data but you will get the idea):
SELECT *
FROM TRXN_REPORT CNT
LEFT JOIN TBL_DEAL_EVT EVENT ON
CNT.INTERNAL_REF_NUM = EVENT.INTERNAL_REF_NUM
AND CNT.BRANCH = EVENT.BRANCH
AND CNT.QFXVERSION = EVENT.QFXVERSION
AND CNT.VALUEDATE = EVENT.VALUEDATE
LEFT JOIN SOME_OTHER_TABLE T ON
...
WHERE
AND CUSTADDINFO.REC_STATUS ='O'
AND CIFMISC.REC_STATUS = 'O'
AND MY_PBG_CUSTOMER = 'Y'
AND (BUYCCYCODE = 'USD' OR SELLCCYCODE ='USD')
....
This way you can safely use LEFT JOIN and the lines for which the records doesn't exist in the other table will also be included.
... to get records which are not there in TBL_MISCADDR table but
present in TRXN_BATCHREPORT_WRK.
That would be done using TRXN_BATCHREPORT_WRK LEFT JOIN TBL_MISCADDR ON <condition>.

Related

SQL Server mismatch row count in SELECT and UPDATE query with same conditions

I am trying to match the update and select query count with same condition. but row count is coming with big difference.
UPDATE Query:
UPDATE MKP set MKP.Quantity = MKP.Quantity + LQD.Quantity, ModifiedDate = GETDATE()
FROM IM_MarketPlace MKP
INNER JOIN IM_ChannelListings CL ON MKP.ListingID = CL.ListingID
INNER JOIN #ListingQuantityData LQD ON LQD.ChanelListingID = RTRIM(LTRIM((CL.ChannelListingID))) and LQD.SalesChannelID = CL.ChannelID
Left outer join IM_ListingVariations LV on LV.ListingCode = RTRIM(LTRIM((LQD.VariationSKU))) and MKP.ListingVariationID = LV.ID and CL.ListingID=LV.ListingID
WHERE MKP.IsActive =1 and MKP.IsDeleted=0 and CL.IsActive =1 and CL.IsDeleted=0
AND (LQD.VariationSKU is null OR (LQD.VariationSKU = LV.ListingCode and lv.ID = MKP.ListingVariationID))
Select Query
select count(mkp.ListingID) FROM IM_MarketPlace MKP
INNER JOIN IM_ChannelListings CL ON MKP.ListingID = CL.ListingID
INNER JOIN #ListingQuantityData LQD ON LQD.ChanelListingID = RTRIM(LTRIM((CL.ChannelListingID))) and LQD.SalesChannelID = CL.ChannelID
Left outer join IM_ListingVariations LV on LV.ListingCode = RTRIM(LTRIM((LQD.VariationSKU))) and MKP.ListingVariationID = LV.ID and CL.ListingID=LV.ListingID
WHERE MKP.IsActive =1 and MKP.IsDeleted=0 and CL.IsActive =1 and CL.IsDeleted=0
AND (LQD.VariationSKU is null OR (LQD.VariationSKU = LV.ListingCode and lv.ID = MKP.ListingVariationID))
Please help me out for this.
and also please let me know how ##rowcount will work for update query.
this will happen if there is a one to many relationship between at least two of the tables involved in the joins.
The SELECT will count all rows including those multiplied out by the join. The UPDATE will just count the unique rows in IM_MarketPlace affected by the UPDATE.
Where there is a one to many relationship it is not deterministic which of the "many" rows joining to a specific row in IM_MarketPlace are used as the source in the update for that row.

Access left join not working as I am picturing it

I am trying to write a query that involves 3 tables and left joining two of them onto a main one.
SELECT UNIT_MAIN.UNIT_NO, DEPT_MAIN.LEV_2, Card.CardNumberLong AS [Some
Number], Card.Enabled, F_CARD.CARD_NO, F_CARD.END_DT
FROM (((UNIT_MAIN
INNER JOIN DEPT_MAIN ON UNIT_MAIN.USING_DEPT = DEPT_MAIN.DEPT_ID)
LEFT JOIN Card ON (UNIT_MAIN.UNIT_NO = Card.UnitCode AND Card.Enabled = True) )
LEFT JOIN F_CARD ON (UNIT_MAIN.UNIT_ID = F_CARD.ASSIGNED_ID AND (F_CARD.END_DT) Is Null ))
WHERE (((UNIT_MAIN.STATUS)="A") AND ((DEPT_MAIN.LEV_2)="AM") AND ((Card.Enabled)=True) )
OR (((UNIT_MAIN.STATUS)="D") AND ((DEPT_MAIN.LEV_2)="AM") AND ((Card.Enabled)=True) )
The issue I am having is when F_CARD table has rows where the F_CARD.END_DT is not null, causing the main table (unit table) not to show up even though it is a left join and the F_CARD table rows did not satisfy the join condition (or I am to believe).
I don't have any where clauses on the F_CARD table and they are only on the join condition.
edit
When I perform
LEFT JOIN MFIVE_F_CARD ON (MFIVE_UNIT_DEPT_COMP_MAIN.UNIT_ID = MFIVE_F_CARD.ASSIGNED_ID AND ((MFIVE_F_CARD.END_DT) Is Null)
The unit does not appear if the F_CARD table contained rows that had an END_DT, I was to believe that since the left join condition failed, the inner table (unit table) should appear regardless.
If I remove any F_CARD related values from the query, the missing units I am looking for appear. It is an inner join, left join, left join. When the second left join happens, I lose rows even when they should appear.
I narrowed down my joins and just did the inner with the left with F_CARD. Trying to see why it doesnt return rows where the join fails.
Tried to do the following, however im getting an unsupported join error...
SELECT
UNIT_MAIN.UNIT_NO
,DEPT_MAIN.LEV_2
,Card.CardNumberLong AS [SomeNumber]
,Card.Enabled
,F_CARD.CARD_NO
,F_CARD.END_DT FROM
(
(
(
UNIT_MAIN
INNER JOIN DEPT_MAIN
ON UNIT_MAIN.USING_DEPT = DEPT_MAIN.DEPT_ID
)
LEFT JOIN Card
ON (UNIT_MAIN.UNIT_NO = Card.UnitCode AND Card.Enabled = True)
)
LEFT JOIN F_CARD
ON (UNIT_MAIN.UNIT_ID = F_CARD.ASSIGNED_ID AND F_CARD.END_DT Is Null)
) WHERE
(UNIT_MAIN.STATUS = "A" OR UNIT_MAIN.STATUS = "D")
AND DEPT_MAIN.LEV_2 = "AM"
Thanks.
I have a feeling it's because you have clauses in your joins that are doing boolean checks rather than matching records between the tables, i.e.
Card.Enabled = True and (F_CARD.END_DT) IS NULL
Try changing the query to:
SELECT
UNIT_MAIN.UNIT_NO
,DEPT_MAIN.LEV_2
,Card.CardNumberLong AS [SomeNumber]
,Card.Enabled
,F_CARD.CARD_NO
,F_CARD.END_DT
FROM
(
(
(
UNIT_MAIN
INNER JOIN DEPT_MAIN
ON UNIT_MAIN.USING_DEPT = DEPT_MAIN.DEPT_ID
)
LEFT JOIN Card
ON UNIT_MAIN.UNIT_NO = Card.UnitCode
)
LEFT JOIN F_CARD
ON UNIT_MAIN.UNIT_ID = F_CARD.ASSIGNED_ID
)
WHERE
(UNIT_MAIN.STATUS = "A" OR UNIT_MAIN.STATUS = "D")
AND DEPT_MAIN.LEV_2 = "AM"
AND Card.Enabled = True

Cannot get both records with SQL/Bigquery JOINs

I've got a query that returns order details, I want information from the briisk table for deals it has found. I also want it to display orders even if the briisk table has nothing.
If I add the final line (and flostream.briisk.master = "") my query only returns one result instead of two.
SELECT *
FROM (SELECT orderno,ifnull(dealid,sales_rule) as DealIDCombo from flostream.orders left join mobileheads.surveys on mobileheads.surveys.order_number = flostream.orders.externalreference) as first
INNER JOIN flostream.orders on first.orderno = flostream.orders.orderno
LEFT JOIN flostream.briisk on first.dealidcombo = flostream.briisk.uniquereference
WHERE first.orderno in (359692,359683)
//AND flostream.briisk.master = ""
When you use a left outer join, then you need to include filter conditions on the second table in the on clause. So try this:
SELECT *
FROM (SELECT orderno,ifnull(dealid,sales_rule) as DealIDCombo
from flostream.orders left join
mobileheads.surveys
on mobileheads.surveys.order_number = flostream.orders.externalreference
) as first INNER JOIN
flostream.orders
on first.orderno = flostream.orders.orderno LEFT JOIN
flostream.briisk
on first.dealidcombo = flostream.briisk.uniquereference AND
flostream.briisk.master = ""
WHERE first.orderno in (359692, 359683)
Conditions on the first table should go in the WHERE clause.

SQL Query date from two tables

I am trying to write a query...
select * from inventoryinfo, purchaseorderiteminfo
where inventoryinfo.qtyinstock < inventoryinfo.minqty
and inventoryinfo.AISTATUS = '1'
and inventoryinfo.category <> 'Noritsu Parts'
and inventoryinfo.itemcode = purchaseorderiteminfo.itemcode
and purchaseorderiteminfo.status = '0'
It returns 10 items
On another table this query shows what items are ordered and on their way
select * from purchaseorderiteminfo
where status = '0'
It returns 8 items
I want to join these two query's to list the 10 items, so I have:
select * from inventoryinfo, purchaseorderiteminfo
where inventoryinfo.qtyinstock < inventoryinfo.minqty
and inventoryinfo.AISTATUS = '1'
and inventoryinfo.category <> 'Noritsu Parts'
and inventoryinfo.itemcode = purchaseorderiteminfo.itemcode
and purchaseorderiteminfo.status = '0'
BUT, it only shows 8 items because the other 2 items do not have an open PO for an order for them. Is there a way to have a list with all 10 items, even 2 of them don't have data in the purchaseorderiteminfo table?
You want to use aleft joinbetween the tables. This gets all rows from the main table, and the matching from the left joined.
select * from inventoryinfo
left join purchaseorderiteminfo on inventoryinfo.itemcode = purchaseorderiteminfo.itemcode and purchaseorderiteminfo.status = '0'
where inventoryinfo.qtyinstock < inventoryinfo.minqty
and inventoryinfo.AISTATUS = '1'
and inventoryinfo.category <> 'Noritsu Parts'
You can also use aliases for the tables to shorten the query a bit:
select * from inventoryinfo i
left outer join purchaseorderiteminfo p on i.itemcode = p.itemcode and p.status = '0'
where i.qtyinstock < i.minqty
and i.AISTATUS = '1'
and i.category <> 'Noritsu Parts'
Also notice that I replaced your old-style implicit joins:
from table1, table2
where table1.key = table2.key
with the explicit syntax used in ANSI standard SQL-92 and later:
FROM table1
LEFT [OUTER] JOIN table2 ON table1.key = table2.key
-- the OUTER keyword is optional in many databases.
See Bad habits to kick : using old-style JOINs for some reasons why you want to do this.

Oracle left outer join, only want the null values

I'm working on a problem with two tables. Charge and ChargeHistory. I want to display a selection of columns from both tables where either the matching row in ChargeHistory has a different value and/or date from Charge or if there is no matching entry in ChargeHistory at all.
I'm using a left outer join declared using the ansi standard and while it does show the rows correctly where there is a difference, it isn't showing the null entries.
I've read that there can sometimes be issues if you are using the WHERE clause as well as the ON clause. However when I try and put all the conditons in the ON clause the query takes too long > 15 minutes (so long I have just cancelled the runs).
To make things worse both tables use a three part compound key.
Does anyone have any ideas as to why the null values are being left out?
SELECT values...
FROM bcharge charge
LEFT OUTER JOIN chgHist history
ON charge.key1 = history.key1 AND charge.key2 = history.key2 AND charge.key3 = history.key3 AND charge.chargeType = history.chargeType
WHERE charge.chargeType = '2'
AND (charge.value <> history.value OR charge.date <> history.date)
ORDER BY key1, key2, key
You probably want to explicitly select the null values:
SELECT values...
FROM bcharge charge
LEFT OUTER JOIN chgHist history
ON charge.key1 = history.key1 AND charge.key2 = history.key2 AND charge.key3 = history.key3 AND charge.chargeType = history.chargeType
WHERE charge.chargeType = '2'
AND ((charge.value <> history.value or history.value is null) OR (charge.date <> history.date or history.date is null))
ORDER BY key1, key2, key
You can explicitly look for a match in the where. I would recommend looking at one of the keys used for the join:
SELECT . . .
FROM bcharge charge LEFT OUTER JOIN
chgHist history
ON charge.key1 = history.key1 AND charge.key2 = history.key2 AND
charge.key3 = history.key3 AND charge.chargeType = history.chargeType
WHERE charge.chargeType = '2' AND
(charge.value <> history.value OR charge.date <> history.date OR history.key1 is null)
ORDER BY key1, key2, key;
The expressions charge.value <> history.value change the left outer join to an inner join because NULL results will be filtered out.
A WHERE clause filters the data returned by a join. Therefore when your inner table has null data for a particular column, the corresponding rows get filtered out based on your specified condition. That is why you should move that logic to the ON clause instead.
For the performance issues, you could consider adding indexes on the columns used for joining and filtering.
Have a look at this site, it will be very helpful for you, visual illustration of all the join statements with code samples
blog.codinghorror.com
Quoted of the relevant info in the above link:
SELECT * FROM TableA
LEFT OUTER JOIN TableB
ON TableA.name = TableB.name
Sample output:
id name id name
-- ---- -- ----
1 Pirate 2 Pirate
2 Monkey null null
3 Ninja 4 Ninja
4 Spaghetti null null
Left outer join
produces a complete set of records from Table A, with the matching records (where available) in Table B. If there is no match, the right side will contain null
For any field from an outer joined table used in the where clause you must also permit an IS NULL option for that same field, otherwise you negate the effect of the outer join and the result is the same as if you had used an inner join.
SELECT
*
FROM bcharge charge
LEFT OUTER JOIN chgHist history
ON charge.key1 = history.key1
AND charge.key2 = history.key2
AND charge.key3 = history.key3
AND charge.chargeType = history.chargeType
WHERE charge.chargeType = '2'
AND (
(charge.value <> history.value OR history.value IS NULL)
OR
(charge.date <> history.date OR history.date IS NULL)
)
ORDER BY
key1, key2, key3
Edit: Appears that this is the same query structure used by Rene above, so treat this one as in support of that please.