How to write a SQL query for the below scenario - sql

Sales
order id : 1(primary key)
Billing address id -250
Shipping address id -285
Address table has the below entries
id :250
Addressline1 : XXX
Addressline2 :YYY
id :285
Addressline1 : AAA
Addressline2 :BBB
How to write a query to retrieve the order id, billing address, shipping address in a single query ?

Use the following query with join. The below is a sample code.
select order.orderid,
ad1.Addressline1,
ad1.Addressline2,
ad2.Addressline1,
ad2.Addresslinne2
from order
join address ad1 on ad1.id=order.billingaddressid
join address ad2 on ad2.id=order.shippingaddressid

You can join to the address table multiple times (this uses an outer join -- depends on potential null values):
select s.id,
billing.Addressline1,
shipping.Addressline1
from sales s
left join address billing on s.billingaddressid = billing.id
left join address shipping on s.shippingaddressid = shipping.id
A Visual Explanation of SQL Joins

Related

how to eliminiate the duplicates from SQL table which has two type of data?

I have a table in my database called email. this will store the email address of all customers based on the type of email they provide. there is a column email type which tells the email is business or personal. when a customer provide business email address we will update it under type business and keep the personal email type as Null. when we try to join this table with my query it gives me duplicate data in email column as the email table has two columns(one as NULL, other one has email address). I cannot give a condition where emailaddress is not null because there are customer who doesn't have provided any email address so both of their emailtype will be null. so those records will be avoided from my query. please help me how to pull the correct email address without pulling the deplicate
I have tried using the condition where emailaddress is not null. but the query result is avoiding the data where both the emailtypes are null
select distinct
c.rtlrcontractidentifier as RetailerID,
CT.Fullname as Fullname,
ad.address1 as Address,
ad.City,
ad.provinceorstate as State,
ad.postalcode as Zip
, e.emailaddress
from contract c
inner join siteidentification si on si.siteoid=c.siteoid
inner join consumer cs on cs.consumeroid=c.billingconsumeroid
inner join contact ct on ct.contactoid=cs.billingcontactoid
left Join Address ad on ad.FKObjectOID = ct.contactOID
and ad.fktableobjectoid=1049
left join email e on e.contactoid=ct.contactoid
where c.rtlrcontractidentifier in('AG74113048'
)
I need to get the emailaddress which is updated but not with the duplicate(null). also should get the data where there is no emailaddress on both emailtypes.
What happened is that you have rows in email table, with contact_oid, and email_type
It is not specified, but I assume your email table:
contact_oid, email_type, email_address
For business emails, it will be email_type = 'B' and for personal emails, the email_type = NULL. To find only emails record that is available, instead of placing a WHERE on the email_type, use the contact_oid to determine if the row exists or not.
In this case, just changing the LEFT JOIN to INNER JOIN should work. If this is not the case, then provide some sample data to work on.
SELECT DISTINCT
c.rtlrcontractidentifier AS RetailerID
, ct.Fullname AS Fullname
-- , e.emailtype --> To show the email type
, e.emailaddress
FROM contracts AS c
INNER JOIN consumer AS cs ON cs.consumeroid = c.billingconsumeroid
INNER JOIN contact AS ct ON ct.contactoid = cs.billingcontactoid
--> Change from LEFT JOIN to INNER JOIN
INNER JOIN email AS e ON e.contactoid = ct.contactoid
WHERE c.rtlrcontractidentifier IN ('AG74113048');
I believe that another way to avoid duplicates is to specify two columns for business email and personal email:
SELECT DISTINCT
c.rtlrcontractidentifier as RetailerID,
.
.
.
be.emailaddress as businesss_email,
pe.emailaddress as personal_email
FROM contract c
.
.
.
LEFT JOIN email be on be.contactoid=ct.contactoid
LEFT JOIN email pe on pe.contactoid=ct.contactoid
WHERE c.rtlrcontractidentifier in('AG74113048') AND
be.email_type = 'Business' AND
pe.email_type = 'Personal'
If you don't like having the two columns, you should be able to combine them with:
SELECT DISTINCT
c.rtlrcontractidentifier as RetailerID,
.
.
.
ISNULL(be.emailaddress, pe.emailaddress) AS emailaddress
FROM contract c
.
.
.
LEFT JOIN email be on be.contactoid=ct.contactoid
LEFT JOIN email pe on pe.contactoid=ct.contactoid
WHERE c.rtlrcontractidentifier in('AG74113048') AND
be.email_type = 'Business' AND
pe.email_type = 'Personal'
In the above query, you will get the business email if it's not NULL, otherwise you will get the personal address.

Two group by tables stich another table

I have 3 tables I need to put together.
The first table is my main transaction table where I need to get distinct transaction id numbers and company id. It has all the important keys. The transaction ids are not unique.
The second table has item info which is linked to transaction id numbers which are not unique and I need to pull items.
The third table has company info which has company id.
Now I've sold some of these with the first one through a group by id. The second through a subquery which creates unique ids and joins onto the first one.
The issue I'm having is the third one by company. I cannot seem to create a query that works in the above combinations. Any ideas?
As suggested here is my code. It works but that's because for the company I used count which doesn't give the correct number. How else can I get the company number to come out correct?
SELECT
dep.ItemIDAPK,
dep.TotalOne,
dep.company,
company.vendname,
appd.ItemIDAPK,
appd.ItemName
FROM (
SELECT
csi.ItemIDAPK,
sum(f.TotalOne) as TotalOne,
count(f.DimCurrentcompanyID) company
FROM dbo.ReportOne F with (nolock)
INNER JOIN dbo.DSaleItem csi with (nolock)
on f.DSaleItemID = csi.DSaleItemID
INNER JOIN dbo.DimCurrentcompany cv
ON f.DimCurrentcompanyID = cv.DimCurrentcompanyID
INNER JOIN dbo.DimDate dat
on f.DimDateID = dat.DimDateID
where (
dat.date >='2013-01-29 00:00:00.000'
and dat.date <= '2013-01-30 00:00:00.000'
)
GROUP BY csi.ItemIDAPK
) as dep
INNER JOIN (
SELECT
vend.DimCurrentcompanyID,
vend.Name vendname
FROM dbo.DimCurrentcompany vend
) As company
on dep.company = company.DimCurrentcompanyID
INNER JOIN (
SELECT
c2.ItemIDAPK,
ItemName
FROM (
SELECT DISTINCT ItemIDAPK
FROM dbo.dimitem AS C
) AS c1
JOIN dbo.dimitem AS c2 ON c1.ItemIDAPK = c2.ItemIDAPK
) as appd
ON dep.ItemIDAPK = appd.ItemIDAPK
For further information my output is the following example, I know the code executes and the companyid is incorrect as I just put it with a (count) in their to make the above code execute:
Current Results:
Item Number TLS CompanyID Company Name Item Number Item Name
111111 300 303 Johnson Corp 29323 Soap
Proposed Results:
Item Number TLS CompanyID Company Name Item Number Item Name
111111 300 29 Johnson Corp 29323 Soap

PostgreSQL - Creating temporary columns instead of multiple rows

I'm working with PostgreSQL customer records.
My task is to export customer records.
I have another table aside from customers with contact information.
One contact item per line (phone, value or email, value, etc.).
When I join and relate the data, I pull multiple records per customer ID (if more than 1 comm type for each customer, example phone and email).
How could I instead of making another row for each comm type, put the info into a temporary column like a phone column, a fax column, and an email column -- then have only 1 row for each customer.
edit -- you guys are masters
Database tables w/ columns:
account {
id
accountid
title (company name?)
shiptoaddress_id (links to address table)
billtoaddress_id (links to address table)
}
address {
city
country
state
name (company name?)
street1
street2
street3
zip
id
}
comlink {
isdeleted
type [Phone,Fax,E-mail,Cell,IM,FaceBook,Twitter,LinkedIn,Web Site,Other]
value
id
party_id (links to party table)
}
party {
isdeleted [t,f]
firstname
lastname
prefix
salutation
suffix
id
address_id
jobtitle_id
}
party_comlinks {
party_id (links to party table ex: fname lname...)
comlinks_id (links to comlink table phone, email, etc 1 item per row)
}
So what I want to do is pull all customers with the following data:
customer.id, customer.accountid, customer.title, shipping.name, shipping.street1, shipping.street2, shipping.street3, shipping.city, shipping.state, shipping.zip, billing.name, billing.street1 (etc), billing.city, billing.state, billing.zip, party.contactperson (as party.firstname + party.lastname) AND have phone, email, fax
I'm not sure if this will be possible as in the system I think you can have multiple shipping info, billing info, contact info for each customer... however where each shipping info and billing info is the same, I only want one row of phone, email, fax, etc and not multiple rows for each phone, email, fax, etc.
Clear as mud, right? :-)
edit -- may have gotten it now, but would still appreciate input
SELECT account.id, account.accountid, account.status, account.title AS "customer",
party.firstname AS "firstname", party.lastname as "lastname", address.name AS "billname",
address.street1 AS "billtostreet1", address.street2 AS "billtostreet2", address.city as "billtocity",
address.state AS "billtostate", address.zip AS "billtozip", address2.name AS "shiptoname",
address2.street1 as "shiptostreet1", address2.street2 AS "shiptostreet2", address2.city AS "shiptocity",
address2.state AS "shiptostate", address2.zip AS "shiptozip",
((SELECT a.value
FROM public.comlink a, party_comlinks b
WHERE b.party_id=party.id AND b.comlinks_id=a.id AND a.type='Phone')) AS "phone",
((SELECT a.value
FROM public.comlink a, party_comlinks b
WHERE b.party_id=party.id AND b.comlinks_id=a.id AND a.type='Fax')) AS "fax",
((SELECT a.value
FROM public.comlink a, party_comlinks b
WHERE b.party_id=party.id AND b.comlinks_id=a.id AND a.type='E-Mail')) AS "email"
FROM ( public.account account
INNER JOIN public.party party ON account.contact_id = party.id )
INNER JOIN public.comlink comlink ON party.id = comlink.party_id
INNER JOIN public.address address ON account.billtoaddress_id = address.id
INNER JOIN public.contact contact ON account.contact_id = contact.id
LEFT JOIN public.contact_shiptoaddress contact_shiptoaddress ON contact.id = contact_shiptoaddress.contact_id
LEFT JOIN public.address address2 ON contact_shiptoaddress.shiptoaddress_id = address2.id
WHERE account.isdeleted = 'f'
--WHERE ((comlink.type = 'E-Mail'))
--AND ((account.walkin is null OR (NOT ( account.walkin ))))
--AND ((NOT ( (account."status" = 'CustomerStatusInactive') )))
--AND ((account."prospect" is null
--OR (NOT ( account."prospect" ))))
ORDER BY account.id ASC
Actually, the INNER JOIN's were not what I needed... I needed to do LEFT JOIN's as described below.
You'll have to do this by explicitly joining against the contact table multiple times. There is now way to have a "dynamic" set of output columns depending on the data.
Example:
SELECT customers.name, phone_contacts.value AS phone, fax_contacts.value AS fax, ...
FROM customers
LEFT JOIN (SELECT * FROM contacts WHERE contact_type = 'phone') AS phone_contacts ON ...
LEFT JOIN (SELECT * FROM contacts WHERE contact_type = 'fax') AS fax_contacts ON ...

Using conditions in joins

I've below 3 tables from which need to fetch address for the records.
1. Address AD
---> It has all the address values(addrline1,addrline2,state,etc..) alongwith AddressID column
2. Address_Employee AE
---> It has EmpID,AddressID,AddressTypeID columns
There can be multiple instances of same EmpID with different AddressID and AddressTypeID value as either 3 or 1
3. Address_Type AT
---> There are 2 rows, with AddressTypeID and AddressType columns. AddressTypeID value with 1 will be Home and 3 will be Postal.
Need to fetch records in such a way that first need to look for Postal address, if not available then Home.
I'm using the query:
SELECT (AD.sAddressLine1+' '+AD.sAddressLine2+' '+AD.sSuburb+' '+AD.sPostCode) AS Address
from Address AD
INNER JOIN Address_Employee AE ON AD.AddressID = AE.AddressID
INNER JOIN Address_Type AT ON AE.AddressTypeID= AT.AddressTypeID
But how can I apply the condition: "first need to look for Postal address, if not available then Home."
Please advise.
Thanks, Krishna
You could create a view delivering the preferred address for every EmpID, and use this for furthor joins.
Create View V_Emp_With_Preferred_Address as
Select Distinct EmpID
,Case when Exists(Select * from Address_Employee where Address_Employee.EmpID=e.EmpID and AddressTypeID=3) then
( -- take preferred postal address if available
Select ISNULL(sAddressLine1+' ','')+ISNULL(sAddressLine2+' ','')+ISNULL(sSuburb+' ','')+ISNULL(sPostCode,'')
from Address_Employee
join Address on Address.AddressID=Address_Employee.AddressID
where Address_Employee.EmpID=e.EmpID and AddressTypeID=3
)
else
(
Select ISNULL(sAddressLine1+' ','')+ISNULL(sAddressLine2+' ','')+ISNULL(sSuburb+' ','')+ISNULL(sPostCode,'')
from Address_Employee
join Address on Address.AddressID=Address_Employee.AddressID
where Address_Employee.EmpID=e.EmpID and AddressTypeID=1
)
end as Address
from dbo.Address_Employee e

Left Join that always includes null records

I'm using Oracle 11gR2 and I am trying to write a query that returns address data from two tables, CUSTOMERS and LOCATIONS. A given customer may (or may not) have different locations, each with their own address.
I would like to return the address for every customer, and all their locations. For example, if the tables contained data like:
CUSTOMERS
CUSTOMER_ID ADDRESS
1 "New York"
2 "California"
LOCATIONS
CUSTOMER_ID LOCATION_ID ADDRESS
1 1 "New Jersey"
Then I want the results to look like:
CUSTOMER_ID LOCATION_ID ADDRESS
1 "New York"
1 1 "New Jersey"
2 "California"
My first thought was something like this:
SELECT
CUSTOMERS.CUSTOMER_ID,
LOCATIONS.LOCATION_ID,
NVL(LOCATIONS.ADDRESS,CUSTOMERS.ADDRESS) ADDRESS
FROM
CUSTOMERS
LEFT JOIN
LOCATIONS ON (CUSTOMERS.CUSTOMER_ID=LOCATIONS.CUSTOMER_ID)
The problem with that is that when a customer does have locations, it does not return a row with null values for location data, so I don't get a row with the address in the CUSTOMERS table. It gives me something like this:
CUSTOMER_ID LOCATION_ID ADDRESS
1 1 "New Jersey"
2 "California"
It's missing the New York address for customer 1. I tried this...
SELECT
CUSTOMERS.CUSTOMER_ID,
LOCATIONS.LOCATION_ID,
NVL(LOCATIONS.ADDRESS,CUSTOMERS.ADDRESS) ADDRESS
FROM
CUSTOMERS
LEFT JOIN
LOCATIONS ON (CUSTOMERS.CUSTOMER_ID=LOCATIONS.CUSTOMER_ID OR LOCATIONS.CUSTOMER_ID IS NULL)
But it gave me the same results as the first query. Is there a way to return a null record for the second table even when there is a match on the join condition?
You don't need a join here at all:
SELECT customer_id, NULL AS location_id, address
FROM customers
UNION ALL
SELECT customer_id, location_id, address
FROM locations
You can try a full outer join. For example:
SELECT
CUSTOMERS.CUSTOMER_ID,
LOCATIONS.LOCATION_ID,
NVL(LOCATIONS.ADDRESS,CUSTOMERS.ADDRESS) ADDRESS
FROM CUSTOMERS
FULL OUTER JOIN LOCATIONS ON (CUSTOMERS.CUSTOMER_ID=LOCATIONS.CUSTOMER_ID)
If you want to join the two tables even when there is a non match, you will need to use IS NULL on your joined columns.
For example.
Table 1:
CustomerID
CustomerName
.
Table 2:
CustomerID
CustomerEmail
.
Select,
CustomerID,
CustomerName,
ISNULL (CustomerEmail, NULL) AS CustomerEmail
FROM table1
LEFT JOIN table2
ON table1.CustomerID = table2.CustomerID
This wil bring back results with NULL