Listing Pairs on same table with different criteria on Oracle Sql - sql

I need to list pairs of customer names as follows;
> CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME, CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME
such that each pair of customers has the same zip code (which is also in the customers table).
On the task there is a hint which says
HINT: Your output should have four columns: CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME, CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME
This is what I have written so far:
SELECT DISTINCT CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME, CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME
FROM CUSTOMERS
WHERE CUSTOMER_ZIP = CUSTOMER_ZIP
But I am not sure how to continue since I've only started learning SQL yesterday. I have also tried to Join the same table which resulted in ambiguity errors.
Update#1:
I've written this code using aliases as suggested by #kpater87
SELECT DISTINCT C1.CUSTOMER_FIRST_NAME, C1.CUSTOMER_LAST_NAME , C2.CUSTOMER_FIRST_NAME, C2.CUSTOMER_LAST_NAME
FROM CUSTOMERS C1
INNER JOIN CUSTOMERS C2
ON C1.CUSTOMER_ZIP = C2.CUSTOMER_ZIP
But even though I have a distinct statement it will show duplicate data. Is this to be expected or am I missing something?

Your updated query looks fine. The only problem in your query is it will be joining also the same records.
If you have a primary key in the table you can improve your query by adding WHERE condition:
SELECT DISTINCT C1.CUSTOMER_FIRST_NAME,
C1.CUSTOMER_LAST_NAME ,
C2.CUSTOMER_FIRST_NAME,
C2.CUSTOMER_LAST_NAME
FROM CUSTOMERS C1
INNER JOIN CUSTOMERS C2
ON C1.CUSTOMER_ZIP = C2.CUSTOMER_ZIP
WHERE C1.PK <> C2.PK;
PK - is a column being a primary key in the table.
If you don't have primary key you can try this one:
SELECT C1.CUSTOMER_FIRST_NAME,
C1.CUSTOMER_LAST_NAME ,
C2.CUSTOMER_FIRST_NAME,
C2.CUSTOMER_LAST_NAME
FROM CUSTOMERS C1
INNER JOIN CUSTOMERS C2
ON C1.CUSTOMER_ZIP = C2.CUSTOMER_ZIP
WHERE C1.CUSTOMER_FIRST_NAME <> C2.CUSTOMER_FIRST_NAME
AND C2.CUSTOMER_LAST_NAME <> C2.CUSTOMER_LAST_NAME
But there still be a problem that in your output you will get e.g.
Mary Smith James Bond
James Bond Mary Smith
To remove permutations:
SELECT C1.CUSTOMER_FIRST_NAME,
C1.CUSTOMER_LAST_NAME ,
C2.CUSTOMER_FIRST_NAME,
C2.CUSTOMER_LAST_NAME,
C1.CUSTOMER_ZIP
FROM T_CUSTOMERS C1
LEFT JOIN T_CUSTOMERS C2
ON (C1.CUSTOMER_ZIP = C2.CUSTOMER_ZIP
AND
C1.CUSTOMER_NUMBER > C2.CUSTOMER_NUMBER );
See also: SQL: self join using each rows only once

Related

SQL JOIN to get the compare two values/row from table "A" and the same row from table "B"

I have two tables with the following rows
Table A (transaction)
Order Seller Customer
1 300 500
Table B (Persons)
PersonID FullName
300 Peter White
500 Scott Bold
I want a result like this
Order Seller Customer FullName (Seller) FullName (customer)
1 300 500 Peter White Scott Bold
I've tried multiple things however which makes more sense is a join a table twice, however I'm getting:
Ambiguous column name
This is SQL Server 2019.
Basically I'm looking to retrieve info from the same table instead of creating additional tables. Is that possible? If yes, how do you do? Thank you in advance.
As #jarlh wrote in comment:
select t.order, t.seller, t.customer, sel.fullname, cust.fullname
from transaction t
join persons sel -- sel is an alias to persons table
on sel.personid = t.seller
join persons cust
on cust.personid = t.customer;
Query with join will return the result as long as both seller and customer exist in persons table -- here it should as source table names transactions :).
I have another form of query it still join table B twice.
This is archaic syntax which I don't recommend but for beginner know the concept of JOIN:
select t.*,B.FullName as FullName (customer) from
(
select A.Order,A.Seller,A.Customer,B.FullName as FullName(Seller)
from A,B where A.Seller=B.PersionID
) t, B where t.Customer=B.PersionID
The proper way of JOIN:
select t.*,B.FullName as FullName (customer) from
(
select A.Order,A.Seller,A.Customer,B.FullName as FullName(Seller)
from A JOIN B ON A.Seller=B.PersionID
) t JOIN B ON t.Customer=B.PersionID
Hoping this can help you.

Return unique row only - TSQL

I have a customer table and order tables. In customer table we have 'Family link' column which is a given ID to each customer. e.g. familyLink: A121, if this customer has a family member in the table they will have this ID too : A121. Basically I need to return all customers with no family members and have made an order_number 2 or 3
Customer table:
CustmID(PK), Name(varchar), familyLink(varchar).
Order table:
OrderID(PK), order_number (varchar), CustmID(FK)
The query I've return which didn't seem to return customers with no family member..
Select Distinct
c.familyLink,
c.name,
o.order_number
From
Customer c
Left join
Order o on c.CustmID = o.CustmID
where
(o.order_number = 2 or order_number=3)
Examples:
Customer table
Custm ID Name FamilyLink
C1 Liam A11
C2 Lucy A12
C3 David A11
C4 Suzy A13
Orders table
OrderID Order_Number CustmID
O1 2 C1
O2 3 C2
O3 2 C4
Results`
This query should return Lucy and Suzy because they don't have any family members in the customer table..
Any idea why this is returning customers who share familyLink?
Any help appreciated.
Any idea why this is returning customers who share familyLink ?
Because nothing in your query is limiting it to that. You're asking for all rows where you the o.order_number = 2 or order_number = 3; there's nothing about "not returning customers that don't have a family link".
You also have a syntax error in your SQL, specifically Left join Order. ORDER is a Reserved Keyword in SQL Server, and in most (if not every) SQL language. It is strongly advised that you do not give objects names that are a Reserved keyword or a Future Keyword. If you do have an object that has an Reserved Keyword for a name, you must quote it: [Order].
As for what you are after, this is a total guess, but perhaps:
WITH CTE AS(
SELECT C.familyLink,
C.name,
O.order_number,
COUNT(C.CustmID) OVER (PARTITION BY O.order_number) AS Customers
FROM Customer C
INNER JOIN [Order] O ON C.CustmID = O.CustmID --This is an INNER JOIN, as the WHERE must be met, so there can never not be a row
WHERE O.order_number IN (2,3))
SELECT C.familyLink,
C.name,
C.order_number
FROM CTE
WHERE Customers = 1;
If this doesn't work, you'll need to provide sample data and expected results. I put this an answer, however, as my opening statements were also far too long for a comment.

SQL Multiple Joins Query

Here I have two tables committee_colleges and colleges.
Structure of tables is something like this
committee_colleges
committeeCollegeId collegeId committeeMemberId
1 2 1
2 2 2
3 3 2
I am storing committeeMemberId from committeeMember table.And one college can have multiple committee Members.How can I wite a query to display only the colleges assigned to specific committee Member.
For Example,if committeeMember by id=2 has logged in I want to display colleges by id=2,3.
In college table I have like this,
collegeId typeName
1 AICTE
2 NCTE
3 NTCS
This is Committee Member table
committeeMemberId name
1 xyz
2 abc
Now I am writing something like this,but i know its wrong because I dont know how to take it from College table since I am displaying College details.
SELECT cc.committeeCollegeId as committeeCollegeId,
c.collegeId as collegeId,
cc.committeeMemberId as committeeMemberId
FROM committee_college as cc
left outer join College as c
on cc.collegeId = c.collegeId
where cc.committeeMemberId=:committeeMemberId
order by cc.committeeCollegeId asc
Can anyone tell how to display colleges based on its assignment to particular committeeMember?
You were close, you need INNER JOIN instead of LEFT JOIN:
SELECT DISTINCT C.typeName --<<== put here all the columns that you want in output
FROM committee_colleges CC
INNER JOIN college C
ON C.collegeId = CC.collegeId
WHERE CC.committeeMemberId = 2 --<<== your input parameter
EDIT: added DISTINCT
Hope it helps.
You can use below sql statement for the same
DECLARE #committeeMemberId INT = 2 -- Id of Committee member
;WITH CTE_MemberCommittee AS
(
SELECT CollegeId
FROM committee_colleges
WHERE committeeMemberId = #committeeMemberId
)
SELECT collegeId, typeName
FROM college
WHERE collegeId IN (SELECT CollegeId FROM CTE_MemberCommittee)
You can use simple inner join for that,
If you want collegename based on memberId use following query,
select a.collegeid,a.typeName from
college a, committee_colleges b, committe_member c
where a.collegeid = b.collegeid and
b.committeememberid = c.committeeMemberId
and c.committeeMemberId = '2'
If you want collegename based on committemember name then use following query,
select a.collegeid,a.typeName from
college a, committee_colleges b, committe_member c
where a.collegeid = b.collegeid and
b.committeememberid = c.committeeMemberId
and c.Name = 'xyz'
Hope it will help.
try this:
DECLARE #LoginCommitteeMemberId INT=2
SELECT t2.Name AS MemberName,
t3.TypeName AS CollageName
FROM committee_college t1
INNER JOIN Committee_Member t2
ON t1.committeeMemberId = t2.committeeMemberId
INNER JOIN College as t3
ON t1.collegeId = t3.collegeId
WHERE t1.committeeMemberId = #LoginCommitteeMemberId

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

Selecting from table with categories of people

I created a database in ms sql , in the database I have three category of persons namely staff, customers, suppliers whom I stored in different tables create serial unique id for each.
Now these persons id are stored under person_id and a column names person type which stores whether its a staff, custimer or supplier in the transaction table, The problem lies in selecting the records from the transaction table like this pseudo code
Select t.*,s.na as staff,sp.name as supplier, c.name as customer
From Trans t
left join Staff s on s.id = t.pid
left join Suppliers sp on sp.id = t.pid
left join Customers c on c.id = t.pid
This returns one row, instead of at least 3 or more, How do I solve this problem
My trans table
person_id Person_type Trans_id
1 staff 1
1 customer 2
2 customer 3
3 suppler 4
1 staff 5
Expected output
person_name Trans_id
james 1
mark 2
dan 3
jude 4
james 5
Staff, Customers, and suppliers are stored in their different tables
That's what the Join does, combine data from multiple tables into one result row. If you want to "keep the rows", not combine them, you can use UNION
(
Select t.* From Trans t
left join Staff s on s.id = t.pid
)
UNION
(
Select t.* From Trans t
left join Suppliers sp on sp.id = t.pid
)
UNION
(
Select t.* From Trans t
left join Customers c on c.id = t.pid
)
This will get you the multiple rows you want BUT still not sure you have defined it right. I see you are only taking columns from Trans, so you're not getting any data from the other tables. And you're doing left outer joins so the other tables won't affect the selection. So I think it's just that same as selecting from just Trans.
If what you want is data from Trans where there is corresponding entry in the other tables, then do the UNION, but also change the outer joins to inner.