How to find the shared value between two values in another column? - sql

I need to list supplier names of parts shipped by both S2 and S4. I have 3 tables named S, P, and SP but S and SP are the only ones I need.
SP table
sno | pno |
s1 p1
s2 p1
s2 p2
s4 p2
s4 p4
s4 p5
S table
sno | sname
S1 Smith
s2 Jones
s4 Clarke
I just have so far:
SELECT s.sname FROM s INNER JOIN sp ON s.sno = sp.sno

Can you please try this:
SELECT sname
FROM s WHERE sno IN (SELECT MAX(sno) FROM sp
GROUP BY pno HAVING COUNT(DISTINCT(sno)) > 1)

I need to list supplier names of parts shipped by both S2 and S4
Parts shipped by both s2 and s4:
select pno
from sp
where sno in ('s2','s4')
group by pno
having count(distinct sno) = 2;
Suppliers shipping these parts:
select distinct sno
from sp
where pno in
(
select pno
from sp
where sno in ('s2','s4')
group by pno
having count(distinct sno) = 2
);
Complete query for supplier names for these suppliers:
select sname
from s
where sno in
(
select sno
from sp
where pno in
(
select pno
from sp
where sno in ('s2','s4')
group by pno
having count(distinct sno) = 2
)
);

Try this one:
SELECT s.sname FROM s
INNER JOIN sp a ON a.sno = s.sno
INNER JOIN sp b ON a.sno <> b.sno AND a.pno = b.pno
WHERE a.sno IN ('s2', 's4') AND b.sno IN ('s2', 's4')
GROUP BY s.sno;

Related

list of Employee having 2 products

Can someone help here.
I have table employee. I want to find out list of employees having 2 products(P1,P2).
Emp_id Prd_id
E1 P1
E1 P2
E2 P1
E2 P2
E2 P3
E3 P1
E3 P3
E4 P1
E4 P2
So, I want output as
Emp_id
E1
E4
SELECT emp_id
FROM employee
GROUP BY emp_id
HAVING COUNT(CASE WHEN prd_id 'p1' THEN 1 END) > 0 -- p1 exists
AND COUNT(CASE WHEN prd_id 'p2' THEN 1 END) > 0 -- p2 exists
AND COUNT(CASE WHEN prd_id NOT IN ('p1', 'p2') THEN 1 END) = 0 -- but not other
Easier to extend to a larger number of products:
SELECT emp_id
FROM
( -- get a unique list first
SELECT DISTINCT emp_id, prd_id
FROM employee
) AS dt
GROUP BY emp_id
HAVING SUM(CASE WHEN prd_id IN ('p1', 'p2') THEN 1 ELSE -1 END) = 2
If the requirement is to find employees with any two products, you could use a having condition to count them:
SELECT emp_id
FROM employees
GROUP BY emp_id
HAVING COUNT(*) = 2
If those products must be p1 and p2, you could add another condition on that:
SELECT emp_id
FROM employees
GROUP BY emp_id
HAVING COUNT(*) = 2 AND
COUNT(CASE WHEN prd_id IN ('p1', 'p2') THEN 1 END) = 2

Error if use subquery in group by : Cannot perform an aggregate function on an expression containing an aggregate or a subquery

I have one to one mapping in two tables. For each order there is a purchase, but sometimes purchase are bad so remove association in order table.
But I need an aggregate table grouped by seller , for which seller how many bad purchases and valid purchases are there.
Examples
Order Table
OrderId PurchaseId
-------- -----------
o1 p1
o2 p6
o3 null
o4 p2
o5 p3
Purchase Table
PurchaseId OrderId SellerId
----------- --------- ---------
p1 o1 s1
p2 o4 s1
p3 o5 s2
p4 o2 s2
p5 o3 s3
p6 o2 s4
Aggregare Seller Table
SellerId NullPurchase validPurchase TotalPurchase
--------- ------------- -------------- --------------
s1 0 2 2
s2 1 1 2
s3 1 0 1
s4 0 1 1
Query to get aggregate table
Select SellerId, count(*) as TotalPurchase,
count(case when ((Select count(*) from dbo.Order where purchaseId = p.PurchaseId) = 0) then 1 end) as NullPurchase
count(case when ((Select count(*) from dbo.Order where purchaseId = p.PurchaseId) = 1) then 1 end) as validPurchase
from dbo.Purchase p
left join on dbo.Order o
on p.OrderId = o.OrderId
group by sellerId
I think this is one way to do what you want, if I understand your goal correctly:
Select SellerId, count(*) as TotalPurchase,
sum(case when o.purchaseId IS NULL then 1 end) as NullPurchase,
sum(case when o.purchaseId IS NOT NULL then 1 end) as validPurchase
from dbo.Purchase p
left join on dbo.Order o
on p.OrderId = o.OrderId
AND p.purchaseId = o.purchaseId
group by sellerId
You don't need subqueries:
select p.SellerId, count(*) as TotalPurchase,
count(*) - count(o.OrderId) as NullPurchase,
count(o.OrderId) as validPurchase
from dbo.Purchase p left join
dbo.Order o
on p.OrderId = o.OrderId
group by p.sellerId

query to select non matching records from two tables

I have 2 tables like this:
Table Student_Old:
id name city
1 A X
2 B Y
3 C Z
Table Student_new:
id name city
1 A X
2 M Y
3 C K
As you can see for Id 2,name is mismatching and for Id 3, city is mismatching in both tables(I am doing comparison on ID which is primary key in both table, basically student_new is backup table for old ). Now I want to get these 2 rows which are not matching.
e.g:
student_old s1, student_new s2-
s1.id s2.id s1.name s2.name s1.city s2.city
2 2 B M X X
3 3 C C Z K
Since you don't care about records which are in one table but not in the other, a simple JOIN will suffice:
SELECT s1.id AS old_id, s2.id AS new_id,
s1.name AS old_name, s2.name AS new_name,
s1.city AS old_city, s2.city AS new_city
FROM student_old s1
JOIN student_new s2
ON s1.id = s2.id
WHERE s1.name != s2.name OR s1.city != s2.city
Output:
old_id new_id old_name new_name old_city new_city
2 2 B M Y Y
3 3 C C Z K
SELECT so.id AS id_1, so.name AS name_1, so.city AS city_1,
sn.id AS id_2, sn.name AS name_2, sn.city AS city_2
FROM student_old so
INNER JOIN student_new sn
ON so.id = sn.id
WHERE so.name <> sn.name AND so.city <> sn.city
use join
select os.*,ns.* Student_Old os join Student_new ns on os.id=ns.id
where os.city!=ns.city OR os.name!=ns.name
Use inner join and where clause do filter out non matching name and city
select a.* , b.* from Student_Old inner join Student_new
on a.id=b.id
where a.name<>b.name or a.city<>b.city

SQL Query without duplicates

I have 3 tables like this:
Names:
ID(K) Name
--------------
1 n1
2 n2
Jobs:
ID Job
------------
1 j1
1 j2
Phones:
ID Phone
--------------
1 p1
1 p2
1 p3
1 p4
I'm doing a SELECT with LEFT OUTER JOIN:
SELECT Names.Name, Jobs.Job, Phones.Phone
FROM
Names LEFT OUTER JOIN Jobs ON Jobs.ID = Names.ID
LEFT OUTER JOIN Phones ON Phones.ID = Names.ID
and returns:
n1 j1 p1
n1 j1 p2
n1 j1 p3
n1 j1 p4
n1 j2 p1
n1 j2 p2
n1 j2 p3
n1 j2 p4
n2 null null
but i need this results:
n1 j1 p1
n1 j2 p2
n1 null p3
n1 null p4
n2 null null
what's the solution?
You're not specifying which RDBMS, but this query works on at least SQL Server, PostgreSQL and Oracle. There may be a smarter analytic function to do this, but it escapes me at the moment.
WITH pjobs AS (
SELECT id, job,
ROW_NUMBER() OVER(PARTITION BY id ORDER BY job) rn FROM jobs
), pphones AS (
SELECT id, phone,
ROW_NUMBER() OVER(PARTITION BY id ORDER BY phone) rn FROM phones
)
SELECT name, job, phone
FROM pjobs FULL JOIN pphones ON pjobs.rn = pphones.rn AND pjobs.id = pphones.id
RIGHT JOIN names ON names.id = pjobs.id OR names.id = pphones.id
An SQLfiddle to test with.

find the last record by Person

This is my Data
Id Name Amt
1 ABC 20
2 XYZ 30
3 ABC 25
4 PQR 50
5 XYZ 75
6 PQR 40
I want the last record by every particular Name like :
3 ABC 25
5 XYZ 75
6 PQR 40
I tried group by, but i am missing some thing.
SELECT PatientID, Balance, PReceiptNo
FROM tblPayment
GROUP BY PatientID, Balance, PReceiptNo
Something like this should work:
SELECT p1.*
FROM tblPayment p1
LEFT JOIN tblPayment p2 ON p1.Name = p2.Name AND p1.Id < p2.Id
WHERE p2.Id IS NULL;
See this SQLFiddle
Should be similar to:
SELECT
id,
name,
amt
FROM
myTable mt1
where mt1.id = (
SELECT
MAX(id)
FROM myTable mt2
WHERE mt2.name = mt1.name
)
this should work
select * from (select id, name,amount from test order by id desc)as t1 group by name;
fiddle
One more option
SELECT *
FROM tblPayment p1
WHERE EXISTS (
SELECT 1
FROM tblPayment p2
WHERE p1.Name = p2.Name
HAVING MAX(p2.Id) = p1.Id
)
See demo on SQLFiddle
A possible solution:
Select p.*
from tblPayment p
Inner join (
Select name, max(id) as id
From tblPayment
Group by name
) as latest on latest.id = p.id