MSSQL comparing 2 columns issue - sql

I have two tables:
Customers info, like id,customerName,address etc.. and RecipientOfGoods - customerId, address.
The addresses from both tables differ, the address in customer table is by registration and the address in second table is delivery address. I need to add in the first table the recipient of goods address in order to compare the two type of addresses.
use dwh01
SELECT distinct
cus.[BranchId]
,cus.[CustomerId]
,cus.[CustomerName]
,cus.[Street] as StreetByReg
,del.Street as StreetForDelivery
,cus.[Postalcode] as PKByReg
,del.Postalcode as PKForDelivery
,cus.[City] as CityByReg
,del.City as CityForDelivery
,cus.[PhoneNumber]
,cus.[EMail]
,cus.[IsActive]
,cus.[LastChangeDate]
FROM [dwh01].[live].[DimCustomer] cus
join live.DimRecipientOfGoods del on del.RecipientOfGoodsid = cus.Customerid
where cus.BranchId in('1080','1081') and ltrim(cus.CustomerId) = '99060'
Thats my query, and i do get the needed result, but i also get on second row the same info but in the columns for address from the second table i get the address from first table. The question is how to remove that useless second row appearing and why it happens like this?

JOIN excluding equal rows to get only customers with new addresses.
SELECT distinct
cus.[BranchId]
,cus.[CustomerId]
,cus.[CustomerName]
,cus.[Street] as StreetByReg
,del.Street as StreetForDelivery
,cus.[Postalcode] as PKByReg
,del.Postalcode as PKForDelivery
,cus.[City] as CityByReg
,del.City as CityForDelivery
,cus.[PhoneNumber]
,cus.[EMail]
,cus.[IsActive]
,cus.[LastChangeDate]
FROM [dwh01].[live].[DimCustomer] cus
JOIN live.DimRecipientOfGoods del ON del.RecipientOfGoodsid = cus.Customerid
AND (cus.[Street] <> del.[Street] OR cus.[Postalcode] <> del.[Postalcode] OR cus.[City] <> del.[City])
WHERE cus.BranchId in('1080','1081') and ltrim(cus.CustomerId) = '99060'

Instead of inner join please use left join to get all the customer information from DimCustomer but additional address information from DimRecipientOfGoods only.
Since there are two separate address information in second table and one is exact match from first table. You can have one address information from first table and
in second table you can ignore that address by comparing two addresses. But I am not sure whether this condition will be same for all the customers. You can choose inner join over left join if you want to remove those customers who have
no records in DimRecipientOfGoods table.
use dwh01
SELECT Distinct
cus.[BranchId]
,cus.[CustomerId]
,cus.[CustomerName]
,cus.[Street] as StreetByReg
,del.Street as StreetForDelivery
,cus.[Postalcode] as PKByReg
,del.Postalcode as PKForDelivery
,cus.[City] as CityByReg
,del.City as CityForDelivery
,cus.[PhoneNumber]
,cus.[EMail]
,cus.[IsActive]
,cus.[LastChangeDate]
FROM [dwh01].[live].[DimCustomer] cus
Left join live.DimRecipientOfGoods del on del.RecipientOfGoodsid = cus.Customerid
AND (cus.Street <> del.Street OR cus.Postalcode <> del.Postalcode OR cus.City <> del.City)
where cus.BranchId in('1080','1081') and ltrim(cus.CustomerId) = '99060'

Related

How to join elements with condition?

I have two tables: regions and regions_access_purchases.
I need a way to generate for user result table that have info about his current active purchase (access to region).
If user have no any purchased/accessed region he should get full list of regions.
If he have some purchased regions he should get full regions list with appended from right column about his purchaseEndDate.
I tried different joins, but all of them do not work:
SELECT region_id, translite_name, "purchaseEndDate" FROM regions
FULL OUTER JOIN regions_access_purchases reg_purch ON regions.id = reg_purch.region_id
WHERE user_id = 1 AND
"purchaseEndDate" > now()
I am getting only two regions, but I need to get full list of regions, with column from right with "purchaseEndDate". If "purchaseEndDate" is less than now it should not present, but region should be displayed in list.
Is it's possible to do such join?
http://sqlfiddle.com/#!15/30e72/2
If you move condition from WHERE to FROM statement and change FULL JOIN to LEFT JOIN you will get expected result:
SELECT * FROM regions
LEFT JOIN regions_access_purchases reg_purch ON regions.id = reg_purch.region_id AND user_id = 1 AND "purchaseEndDate" > now()
P.S. Not sure if you need to add purchaseEndDate to query, added it as you had it in your example.

OracleAPPS- Can not get correct results for Suppliers - Bank query

I am trying to fetch suppliers and bank details in Oracle apps. I am able to write a simple query where each supplier has a supplier site attached to it. Few of my sites doesn't have a record in table "iby_pmt_instr_uses_all". But even then I want to show them . So I am using the outer join on this table. But the issue is when I am putting this outer join condition, I am getting double the records in the query. I believe I am missing on some condition, but can not figure out which one.
SELECT *
FROM apps.iby_pmt_instr_uses_all instrument,
apps.iby_account_owners owners,
apps.iby_external_payees_all payees,
apps.iby_ext_bank_accounts ieb,
apps.ap_supplier_sites_all asa,
apps.ap_suppliers asp,
apps.ce_bank_branches_v cbbv
WHERE owners.ext_bank_account_id = ieb.ext_bank_account_id
AND owners.ext_bank_account_id = instrument.instrument_id(+)
AND payees.ext_payee_id = instrument.ext_pmt_party_id(+)
AND cbbv.branch_party_id = ieb.branch_id
AND payees.payee_party_id = owners.account_owner_party_id
AND payees.supplier_site_id = asa.vendor_site_id
AND asa.vendor_id = asp.vendor_id
AND asp.vendor_name = 'PANALYTICAL'
--and ieb.bank_account_num = asa.VENDOR_SITE_CODE
If I add and ieb.bank_account_num = asa.VENDOR_SITE_CODE this condition I get the correct record, but actually this is not the right join, because there is no relationship between these 2 columns, so this will fail for other suppliers.
Can you please suggest what additional join I can put , so that I get the right result.
Thanks

How to return 1st record from group by

Trying to return only the 1st supplier code and have all other fields unaffected.
`Select
Container.Part_Key,
Part.Part_No,
Part.Name,
Part.Revision,
Container.Quantity,
Container.Container_Status,
OP.Operation_No,
Opp.Operation_Code,
Part.Part_Status,
Supplier.Supplier_Code
From Part_v_Container as Container
Join Part_v_Part as Part
ON Part.Part_Key = Container.Part_Key
Join Part_v_Part_Operation as Op
On Op.Part_Operation_Key = Container.Part_Operation_Key
Join Part_v_Operation as OPP
On OPP.Operation_Key = OP.Operation_Key
Join part_v_approved_supplier as Approved
On Approved.part_key = container.part_key
Join common_v_Supplier as Supplier
On Supplier.supplier_no = Approved.Supplier_No
Where Container.Active = '1'
group by container.part_key`
There will be duplicate part numbers, revisions, etc. Not worried about that. I just want the part no to list only one approved supplier to the far right, even though for any given part, there are multiple approved suppliers listed in the database.
Furthermore, the order the database lists the approved suppliers does not matter.
Thanks!
Add a sub query in your select list
( select top 1 supplier.supplier_code
From supplier
Where Supplier.supplier_no = Approved.Supplier_No order by Supplier.supplier_no) as supplier code
This can be the last field in the select list
You could add An appropriate order by.
This would work in SQL Server

Combining tables in SQL (only for for certain rows)

I wasn't even sure how to word this in the subject line. However, I have a SELECT statement that pulls information from an SQL view called CONTACTS (F_ame, L_Name, Address, Email, etc...). I have another view called INVOICES with purchase information for the members in the contacts view. Keep in mind that the INVOICES view has mulitple purchases of varying products for each member. These two views can be linked with a ContactID key
I only need to display a certain product (EADP Package), if purchased, from the INVOICES view on the same line as the member who purchased it. I also need to retain the entire member list in the pull. So, if I use a WHERE clause to only pull that product, It only gives me those who purchased that product. I need to keep the entire member list and still have a column that displays that particular product for those who purchased it. Hope that made sense.
Sorry, but there are 3 views, not 2. Here is what I have so far:
SELECT Contact.FirstName, Contact.LastName, Contact.CFSDesignation, Contact.EMailAddress1, Contact.Telephone1, Contact.DefaultPriceLevelIdName
FROM Contact INNER JOIN
FilteredInvoice ON Contact.ContactId = FilteredInvoice.contactid INNER JOIN
FilteredInvoiceDetail ON FilteredInvoice.invoiceid = FilteredInvoiceDetail.invoiceid
WHERE (Contact.DefaultPriceLevelIdName = 'member') AND FilteredInvoiceDetail.productidname = 'eAudiology 2014 Unlimited On-Demand Package'
This works fine,but only pulls those who purchased the package. I need the entire member list from CONTACTS (about 10,000 records) plus the product column showing the product above for those who purchased it. I belive is has something to do with joins, but can't get my head around it.
Getting Close, but it doesn't like the keyword "ON":
Also. in your previous answer, what are "C" and "I" used for?
SELECT Contact.FirstName, Contact.LastName, Contact.CFSDesignation, Contact.EMailAddress1, Contact.Telephone1, Contact.DefaultPriceLevelIdName
FROM Contact LEFT JOIN
FilteredInvoice ON Contact.ContactId = FilteredInvoice.contactid LEFT JOIN (SELECT FilteredInvoiceDetail.productidname
FROM FilteredInvoiceDetail
WHERE productidname = 'eAudiology 2014 Unlimited On-Demand Package') ON FilteredInvoice.invoiceid = FilteredInvoiceDetail.invoiceid
WHERE (Contact.DefaultPriceLevelIdName = 'member')
SELECT *
FROM Contacts C
LEFT JOIN ( SELECT *
FROM Invoices
WHERE Product = 'EADP Package') I
ON C.ContactID = I.ContactID
This finally worked for me:
SELECT DISTINCT Contact.ContactId,Contact.FirstName, Contact.LastName, Contact.CFSDesignation, Contact.EMailAddress1, Contact.DefaultPriceLevelIdName, productidname
FROM Contact LEFT JOIN
FilteredInvoice ON Contact.ContactId = FilteredInvoice.contactid LEFT JOIN (SELECT FilteredInvoiceDetail.productidname, FilteredInvoiceDetail.invoiceid
FROM FilteredInvoiceDetail
WHERE productidname = 'eAudiology 2014 Unlimited On-Demand Package' OR productidname = 'eAudiology 2014 Unlimited On-Demand Pkg Renewal') I ON FilteredInvoice.invoiceid = I.invoiceid
WHERE (Contact.DefaultPriceLevelIdName = 'member' OR DefaultPriceLevelIdName = 'student')
ORDER BY LastName

SQL Query that sorts information into two new columns based on a third column

I have a table that stores basic site information, another one that stores the site address, and a third table for the phone. My phone table contains phone numbers, and the type of number.
What I want to do is get my site information, and the main contact number and fax number. So far, my statement looks like this:
SELECT site.isiteid,
site.iclientid,
csitecode,
csitename,
binactive,
caddress1,
caddress2,
ccity,
cstateid,
czip,
icountryid,
cattention,
cemail,
cnumber,
cextension
FROM dbo.site
INNER JOIN dbo.address
ON dbo.site.isiteid = dbo.address.isiteid
AND (site.isiteid = 2)
LEFT JOIN dbo.phone
ON dbo.site.isiteid = dbo.phone.isiteid
AND (dbo.phone.iphtypeid = 1)
This gets me all of the information that I need except for the fax number (dbo.phone.iphtypeid=3). Is there a way to add another column to the result called [fax], and populate it when site.isiteid=phone.isiteid AND phone.iphtypeid=3? Thus, the last 4 columns returned would be [cemail][cnumber][cextension][cfax].
RESOLVED
Thank you to all three who answered. All the answers were similar, so I selected the one that had the most detailed explanation. I did need to add the table name to both cnumber references and cextension to avoid ambiguity. Thank you for the responses!
Add another JOIN clause
LEFT JOIN dbo.phone f
ON dbo.site.isiteid = f.isiteid
AND f.iphtypeid = 3
You would then add f.cfax to the SELECT list.
It might also be good to give the other tables aliases so you can distinguish which columns are coming from which tables.
Yes, you can do this by adding another join to dbo.phone. To distinguish between the two uses, you will need to give the second join an alias. So, something like:
SELECT site.isiteid,
site.iclientid,
csitecode,
csitename,
binactive,
caddress1,
caddress2,
ccity,
cstateid,
czip,
icountryid,
cattention,
cemail,
phone.cnumber,
phone.cextension,
phone_fax.cnumber AS cfax
FROM dbo.site
INNER JOIN dbo.address
ON dbo.site.isiteid = dbo.address.isiteid
AND (site.isiteid = 2)
LEFT JOIN dbo.phone
ON dbo.site.isiteid = dbo.phone.isiteid
AND (dbo.phone.iphtypeid = 1)
LEFT JOIN dbo.phone AS phone_fax
ON dbo.site.isiteid = phone_fax.isiteid
AND (phone_fax.iphtypeid = 3)
You could do something like, even though I'm not sure of how you're tables are defined.
SELECT site.isiteid,
site.iclientid,
csitecode,
csitename,
binactive,
caddress1,
caddress2,
ccity,
cstateid,
czip,
icountryid,
cattention,
cemail,
cnumber,
cextension,
CASE WHEN C.iphtypeid = 3 THEN C.cnumber ELSE NULL END [cfax]
FROM dbo.site A
INNER JOIN dbo.address
ON dbo.site.isiteid = dbo.address.isiteid
AND (site.isiteid = 2)
LEFT JOIN dbo.phone C
ON A.isiteid = C.isiteid