comparing data from tables in sql server - sql

I am facing great peril.
I have 2 TABLES--- purchaseTbl and CustomerTbl , which contain:
purchaseTbl : C_ID (int - FK) , Purchase_amt (int)
CustomerTbl: C_ID (int - PK), [other details].
So i want to calculate the sum of all purchases where the C_ID in both the tables match
Thank you
Gru

Use group by clause in your query like this....
SELECT CustomerTbl.C_ID, SUM(Purchase_amt) AS PurchaseSUM FROM CustomerTbl, purchaseTbl WHERE purchaseTbl.C_ID = CustomerTbl.C_ID GROUP BY CustomerTbl.C_ID

SELECT C.C_ID,
--You can add more columns (like customer name) here if you wish
SUM(Purchase_amt) AS SUMP
FROM CustomerTbl C
JOIN purchaseTbl P
ON P.C_ID = C.C_ID
GROUP BY C.C_ID
--If you added more columns in the select add them here too separated with comma
If you just want to know the total amount and not split it into customers then:
SELECT SUM(Purchase_amt) AS SUMP
FROM CustomerTbl C
JOIN purchaseTbl P
ON P.C_ID = C.C_ID
The above will get the total amount only if there is a corresponding C_ID in CustomerTbl.

Related

How to get all rows from one table which have all relations?

I have 3 tables:
companies (id, name)
union_products (id, name)
products (id, company_id, union_product_id, price_per_one_product)
I need to get all companies which have products with union_product_id in (1,2) and total price of products (per company) is less than 100.
What I am trying to do now:
select * from "companies" where exists
(
select id from "products"
where "companies"."id" = "products"."company_id"
and "union_product_id" in (1, 2)
group by id
having COUNT(distinct union_product_id) = 2 AND SUM(price_per_one_product) < 100
)
The problem I stuck with is that I'm getting 0 rows from the query above, but it works if I'll change COUNT(distinct union_product_id) = 2 to 1.
DB fiddle: https://www.db-fiddle.com/f/iRjfzJe2MTmnwEcDXuJoxn/0
Try to join the three tables as the following:
SELECT C.id, C.name FROM
products P JOIN union_products U
ON P.union_product_id=U.id
JOIN companies C
ON P.company_id=C.id
WHERE P.union_product_id IN (1, 2)
GROUP BY C.id, C.name
HAVING COUNT(DISTINCT P.union_product_id) = 2 AND
SUM(P.price_for_one_product) < 100
ORDER BY C.id
See a demo.
SELECT c.name FROM "companies" c
JOIN "products" p ON c.id = p.company_id
WHERE union_product_id IN (1, 2) AND price_for_one_product < 100
GROUP BY c.name
HAVING COUNT(DISTINCT p.name) =2
This would provide you all the company(s) name(s) which has provides both union_product_id 1 and 2 and the price_for_one_product/ price_per_one_product is less than 100.
Note: You might need to change price_for_one_product with price_per_one_product, as in question you have used price_per_one_product but db-fiddle link table defination has used price_for_one_product.

How can I show all "article" which have more than 3 "bids"?

I wanna show the "ArticleName" of all "offers" that have more than 3 "bids". The number of the "Bids" should be output.
I don't know how I can write it down. But I think I know the Logic. It should count the same number of the Table "bid" and the column "OID" and in the end it should paste the number which is more than 3.
Picture:
Well that's easy enough:
Select ArticleName
, count(*) NumberOfBids
from Offer o
join Bid b
on b.oid = o.oid
group by ARticleName
having count(*) >= 3
SELECT * FROM (
SELECT o.ArticleName, count(b.BID) as numberOfBids
FROM Offer as o INNER JOIN bid as b ON o.oid = b.oid
GROUP BY o.ArticleName
) as c
WHERE c.numberOfBids > 3

Joining SQL tables and removing repetitions

I am trying to get a list of the customers with the same phone number, as there are instances of the same customer being created two or three times with slightly different names.
The query below has almost the intended behavior:
SELECT C1.CUSTOMER_NAME, C2.CUSTOMER_NAME, C1.PHONE_NUMBER
FROM CUSTOMER C1
JOIN CUSTOMER C2
ON C1.PHONE_NUMBER = C2.PHONE_NUMBER
WHERE C1.CUSTOMER_NAME != C2.CUSTOMER_NAME
AND C1.PHONE_NUMBER != ''
ORDER BY C1.CUSTOMER_NAME
But I get repetions like:
Customer A - Customer B
Customer A - Customer C
Customer B - Customer A
Customer B - Customer C
Customer C - Customer A
Customer C - Customer B
When all I want to get is the first two lines, which are enough to cover all the cases.
Thanks in advance for the help.
I'm not sure you want just the first two lines . . . because the last line seems different.
In any case, you can replace the != with < to get what you want:
SELECT C1.CUSTOMER_NAME, C2.CUSTOMER_NAME, C1.PHONE_NUMBER
FROM CUSTOMER C1 JOIN
CUSTOMER C2
ON C1.PHONE_NUMBER = C2.PHONE_NUMBER AND
C1.CUSTOMER_NAME < C2.CUSTOMER_NAME
WHERE C1.PHONE_NUMBER <> ''
ORDER BY C1.CUSTOMER_NAME;
If you just want all the customers on a given phone number -- when there is more than one customer -- then you do not need a join:
select c.phone_number, c.name
from (select c.*, count(*) over (partition by phone_number) as cnt
from customer c
) c
where cnt > 1
order by c.phone_number, c.name;
You could use a subquery (or JOIN with same login) to get the duplicate numbers first, then report on all the customers with that number:
SELECT CUSTOMER_NAME, PHONE_NUMBER
FROM CUSTOMER
WHERE PHONE_NUMBER IN (SELECT PHONE_NUMBER
FROM CUSTOMER
WHERE COUNT(PHONE_NUMBER) > 1 AND PHONE_NUMBER != '')
ORDER BY PHONE_NUMBER

How to select members of a special kind of relationship in sql

I have 3 table as follow :
s(s# int,sname nchar(10))
p(p# int,pname nchar(10))
sp(s# int,p# int)
table "s" is table of suppliers and "s#" is primary key of it.also table "p" is table of products and "p#" is primary key on it."s#" and "p#" are foreign key in table "sp".
now my question is "How can I select name of suppliers from table "s" which producing all of products in table "p"...
SELECT p.*, s.sname FROM s, sp, p WHERE s.s# = sp.s# AND sp.p# = p.p#;
This statement will output all products with all their suppliers.
Now we group my suppliers, and count how many products they provide:
SELECT s.sname, count(*) FROM s, sp, p WHERE s.s# = sp.s# AND sp.p# = p.p# GROUP BY s.s#;
Now we know exacly, how many products each supplier provides. And we also know, how many products are in the productstable:
SELECT count(*) FROM p;
If you compare these values, you get your desired result:
SELECT amounts.name FROM
( SELECT s.sname AS name, count(*) AS offers
FROM s, sp, p
WHERE s.s# = sp.s# AND sp.p# = p.p#
GROUP BY s.s# ) amounts, -- this is a temp. tablename
( SELECT count(*) AS avaiable FROM p ) countTbl
WHERE amounts.offers = countTbl.avaiable;
Notice, that I didn't test the query. But you should get an idea on how to solve this problem.
It might also be possible to write this query more efficient, but this one can be understood easily.
There are two ways to do this, the first I thought of was to invert the logic.
Rather than attempting to find every entry of P let's just look for any that don't exist, then exclude those entries from S:
SELECT *
FROM S
WHERE
NOT EXISTS (
SELECT *
FROM P
LEFT JOIN SP
ON P.P# = SP.P#
AND SP.S# = S.S#
WHERE
SP.P# IS NULL
)

sql - find max value

I have a table with 3 columns: Code, Year, percentage.
I need to return the code with the lowest (minimal) percentage in 2009. After this, I want also the name of the code, that exsist in other table that I made.
I only think using CREATE VIEW, but I prefer not to do so.
Select table.code, table.year, table.percentage, othertable.name
from table
inner join othertable on table.FKId = othertable.PKid
where year = 2009
and percentage =
(select min(percentage)
from table
where year = 2009)
Updated to include the othertable... since we don't have names.
UPDATED
Now that we have table names... Updated 3rd time now that I know year is string.
Select E.Code, C.Name
From dbo.Exam E
inner join dbo.Course C
ON E.Code = C.Code
Where E.Year = '2009' and --<-- PROBLEM LIKELY HERE year was string not int.
E.Fail = (select MIN(E2.Fail)
from dbo.Exam E2 where E2.Year = '2009') --<--Don't forget here too.
From comments: sample Data:
INSERT INTO Exam VALUES(333,'2009',40)
INSERT INTO Exam VALUES(333,'2009',20)
INSERT INTO Exam VALUES(555,'2009',19)
INSERT INTO Exam VALUES(444,'2009',19)
INSERT INTO Exam VALUES(777,'2009',23)
INSERT INTO Exam VALUES(333,'2009',0)
INSERT INTO Course VALUES(111,'Name1',5)
INSERT INTO Course VALUES(333,'Name2',5)
INSERT INTO Course VALUES(444,'Name3',6)
INSERT INTO Course VALUES(555,'Name4',3)
INSERT INTO Course VALUES(777,'Name5',3)
INSERT INTO Course VALUES(999,'Name6',6)
Assumption is result should be
Name2, 5
You can use a group by to find the lowest percentage for a year, and then join back to the main tables to find the corresponding other columns:
select *
from CodeYearPercTbl cyp
join CodeTbl c
on c.Code = cyp.Code
join (
select Year
, min(Percentage) as MinPerc
from CodeYearPercTbl
group by
Year
) as filter
on filter.Year = cyp.Year
and filter.MinPerc = cyp.Percentage
where cyp.Year = 2009
Table-1 : Code,Year,Percentage
Table-2 : Code,CodeName
select T1.Code,T2.CodeName,T1.Percentage from
(
select TOP 1 Code,Percentage
from Table-1
where Year = '2009'
order by Percentage asc
) T1 inner join Table-2 T2 on T1.Code = T2.Code
Try this:
select a.Code, c.Name
from YourTable a inner join AnotherTable c on a.Code = c.Code
where a.Percentage = (select MIN(Percentage)
from YourTable b where b.Year = '2009'
)