Display only Companies that does not supply "Beverages" in Microsoft SQL - sql-server

having trouble here with SQL statement for displaying companies that does not supply beverages. Now the problem here is that there are few companies that supply both beverage and other stuff. I need it to only display companies that does not supply beverages at all. When i run my modified SQL statement, i managed to get what i want but, for those companies that supply foods as well as beverages, it is still being displayed because of my WHERE clause i set to search for C.CategoryName != 'Beverages'. I just want to remove those companies that supply both beverages and foods so i can only display those companies that purely supply only foods.
Sorry if i have some grammer mistake or anything or my question is unclear. I just don't really know how to explain professionally as it is hard to describe my problem. Thanks for those who willing to help me, i am really appreciate it. And also i do not know if these info and source codes are sufficient regarding my problem. Will provide more info/source code if needed.
Pictures of Both Category & Products table.
Category Table
Products Table
Here's the Initial statement
SELECT P.ProductName
FROM Products AS P
INNER JOIN
Categories AS C
ON
C.CategoryID = P.CategoryID
AND C.CategoryName = 'Beverages'
Result
So far here's the modified statement
SELECT S.CompanyName, P.CategoryID, C.CategoryID FROM Suppliers AS S
INNER JOIN
Products AS P
ON S.SupplierID = P.SupplierID
LEFT OUTER JOIN
Categories AS C
ON
C.CategoryID = P.CategoryID
AND C.CategoryName != 'Beverages'
Result

Answer Suggested by Martin Smith.
With adding EXCEPT Clause to the SQL statement to my modified SQL statement, i managed to get it done. Here is the Answer to my problem.
SELECT S.CompanyName FROM Suppliers AS S
EXCEPT
SELECT S.CompanyName FROM Suppliers AS S
INNER JOIN
Products AS P
ON S.SupplierID = P.SupplierID
RIGHT JOIN
Categories AS C
ON
C.CategoryID = P.CategoryID
AND C.CategoryName = 'Beverages'

WITH FOODSUPPLIERS AS
(
SELECT DISTINCT SUPPLIERID
FROM PRODUCTS P
JOIN CATEGORY C ON C.CATEGORYID = P.CATEGORYID
WHERE CATEGORYNAME <> 'Beverages'
)
SELECT S.COMPANYNAME FROM SUPPLIERS S
JOIN FOODSUPPLIERS FS ON FS.SUPPLIERID = S.SUPPLIERID
The FOODSUPPLIERS CTE identifies suppliers in PRODUCTS that are not associated with any beverage products, i.e., associated only with food products. It's then a simple matter of joining the CTE to Suppliers to get the records for these suppliers.

Related

Joining multiple tables yields duplicates

In order to retrieve all Projects for a UserId, or all in case the user is admin, I want to join multiple tables. I'm using the statment in a TableAdapter query for MSSQL.
SELECT P.ID, P.CountryID, P.ProjectYear, P.Name, P.Objective, P.StartDate, P.EndDate, P.BaseCampaign, P.ManagerID, P.IsClosed, P.OrganisationUnitID, P.QualitativeZiele, P.QuantitativeZiele,
P.Herausforderungen, P.Learnings, P.ObjectiveQuantitativ, P.Remarks, P.ProjectOverallID, C.Name AS CountryName, O.Name AS OEName, R.RoleName
FROM wc_Projects AS P
INNER JOIN wc_OrganisationUnit AS O ON P.OrganisationUnitID = O.ID
INNER JOIN wc_Countries AS C ON P.CountryID = C.ID
INNER JOIN aspnet_Roles AS R ON C.ID = R.CountryID
INNER JOIN aspnet_UsersInRoles AS UR ON R.RoleId = UR.RoleId
WHERE (#ViewAll = 1) OR (UR.UserId = #UserId)
ORDER BY P.CountryID, P.OrganisationUnitID, P.ProjectYear DESC
In order to apply to the rather static approach for the table adapter, I start with the project.
Get all projects, resolve CountryName and OEName via FK's. Now look if you can find the role that is assoicated to the country. Then find the user that is attached to the role.
I know that this is a terrible query, but it's the only one somewhat applicable to the WebForms TableAdapter way to deal with it.
When I have a UserId that has one or multiple roles associated with countries it works. When a admin user, that has no roles with countries associated but ViewAll = 1 it breaks. I get constraint exceptions and the amount of results nearly tripple.
I tried rewriting the query, adding paranthesis and different joins. But none of it worked. How can I solve this?

Summing a total from multiple sales into a single column

I'm having issues with what I believe should be a simple problem in SQL Server 2017. I need to show the total sales price for a given sale. This is what I have written (note I deleted the totalprice sum formulae because it returned an error) :
USE [Antiques]
GO
DECLARE #TotalPrice INT
SELECT
Sales.SaleNo,
Sales.SalesDate,
Customers.FirstName,
Customers.LastName,
Products.Price,
#TotalPrice AS TotalPrice
FROM
Customers JOIN Sales ON Customers.CustomerID = Sales.CustomerID
JOIN SalesProducts ON Sales.SaleNo = SalesProducts.SaleNo
JOIN Products ON SalesProducts.ProductID = Products.ProductID
WHERE (Products.ProductID = SalesProducts.ProductID)
GO
This is the result:
Even if I remove the item price (which I have just put in temporarily and won't be in final code) there are still multiple lines per sale (1 for each item in the sale). Have I used the wrong joins? How can I get it looking like this:
Can anyone please tell me what I'm doing wrong? I've tried so many ways of using the Sum function and Group By and failing. (Note: this has to be a basic query and not a stored procedure unfortunately)
Actually you're not too far away. I'd move the grouping in a derived table and join that, to get the totalprice.
SELECT sales.saleno,
sales.salesdate,
customers.firstname,
customers.lastname,
x.totalprice
FROM sales
INNER JOIN customers
ON customers.customerid = sales.customerid
INNER JOIN (SELECT salesproducts.saleno,
sum(products.price) totalprice
FROM salesproducts
INNER JOIN products
ON products.productid = salesproducts.productid
GROUP BY salesproducts.saleno) x
ON x.saleno = sales.salesno;

SQL: Summing columns with a similar column in common

I'm extremely new to SQL Sever and so I apologize if the question is worded strange. I am doing a homework assignment, and this is the question:
"A manager wants to know the email address, number or orders, and the total amount of purchases made by each customer. Create a summary query that returns these three items for each customer that has orders."
I have all of the data queried, the problem is when I pull data from each customer, it will show the quantity of items per order, and I need the items to be pooled together into one column. This is my query thus far (again, total noob, please excuse any poor syntax, etc.)
SELECT EmailAddress,
ItemPrice - DiscountAmount * Quantity AS TotalPurchaseAmount,
COUNT(*) AS OrderQty
FROM Customers
JOIN Orders ON Customers.CustomerID = Orders.CustomerID
JOIN OrderItems ON Orders.OrderID = OrderItems.OrderID
GROUP BY Orders.CustomerID,
OrderItems.ItemPrice, OrderItems.DiscountAmount,
OrderItems.Quantity,
Customers.EmailAddress;
The following is a small bit of the result set that I get:
Email Address OrderTotal OrderQty
allan.sherwood#yahoo.com 253.15 2
allan.sherwood#yahoo.com 839.30 2
allan.sherwood#yahoo.com 1208.16 2
barryz#gmail.com 303.79 4
christineb#solarone.com 479.60 2
david.goldstein#hotmail.com 299.00 2
david.goldstein#hotmail.com 489.30 1
david.goldstein#hotmail.com 479.60 1
So as you can see, I have several orders I need to smoosh together into one single row per e-mail, I have looked and looked for an answer but the only thing I can find is how to find duplicates and ignore them, not combine their data. Any help is extremely appreciate, thanks so much for taking the time to read this :) If my question doesn't make sense please let me know so I can clear up any bad wording I may have used!
Just do GROUP BY CustomerID, EmailAddress:
SELECT
c.EmailAddress,
SUM((i.ItemPrice - i.DiscountAmount) * Quantity) AS TotalPurchaseAmount,
COUNT(*) AS OrderQty
FROM Customers c
INNER JOIN Orders o
ON c.CustomerID = o.CustomerID
INNER JOIN OrderItems i
ON o.OrderID = i.OrderID
GROUP BY
c.CustomerID, c.EmailAddress
Additional note: Use aliases for your tables
You need to change your formula and remove columns that you dont want to group by from select query..
for example your query should be something like this
SELECT EmailAddress,
--do your aggregation here
blah AS TotalPurchaseAmount,
COUNT(*) AS OrderQty
FROM Customers
JOIN Orders ON Customers.CustomerID = Orders.CustomerID
JOIN OrderItems ON Orders.OrderID = OrderItems.OrderID
GROUP BY Orders.CustomerID,
Customers.EmailAddress;

Prevent duplicates sql server

Ok, in this query I'm extracting information from 5 tables, the table Company, Programmer, Tester, Manager and the table Contract. I will extract the Programmers', testers', and Managers' Names and Telephone Numbers, as well as the Company they work on, and this company is responsible for managing this program as a request by x person doesn't matter.
Problem is with the code below, a certain information will come out as many times as there is other information, like a programmer's Name and Tel Number will come out as many times as there are Managers and Testers on the company.
I tried with left outer join and it would give me even more results, so how can I fix this so next time a result won't be duplicated but say NULL?
SELECT DISTINCT pg.name,
pg.Tel_Nr,
Mgr.name,
Mgr.Tel_Nr,
Ts.Name,
Ts.Tel_Nr,
Pg.Name,
con.program_name
FROM Company AS Cm
INNER JOIN Programmer AS Pg ON Pg.company = Cm.name
INNER JOIN Manager AS Mg ON Mg.company = Cm.name
INNER JOIN Tester AS Ts ON Ts.company = Cm.name
INNER JOIN Contract AS Con ON Con.program_name = 'My Program'
AND Cm.name = Con.Company
Surely it would make more sense to produce a list of contact details with perhaps a job description. Something like this:
WITH Cte as (select Cm.name from
Contract as Con join Company as Cm on Cm.name = Con.Company
where Con.program_name = 'My Program')
SELECT pg.name, pg.Tel_Nr, 'Programmer' as JobTitle
FROM Cte INNER JOIN
Programmer as Pg on Pg.company = Cte.name
UNION ALL
SELECT Mgr.name, Mgr.Tel_Nr,'Manager' as JobTitle
FROM Cte INNER JOIN
Manager as Mg on Mg.company= Cte.name
UNION ALL
SELECT Ts.Name, Ts.Tel_Nr, 'Tester' as JobTitle
FROM Cte INNER JOIN
Tester as Ts on Ts.company = Cte.name
This solution deploys a Common Table Expression (labelled Cte) to avoid querying thr Company and Contract tables multiple times. Find out more.

How do I build a query that crosses multiple tables?

Here are my tables:
CUSTOMER
Cust_ID (PK)
Name
ORDERS
Order_ID (PK)
Cust_ID (FK)
ORDER_LINE
Order_ID (pk)
Part_ID (FK)
PART
Part_ID (PK)
Part_Description
Now I want to list the customer details, the part number and the description of the parts that each customer ordered.
How do i do this?
Thanks.
You should use "JOIN" using the FK, but from what I see you don't have a foreign key between "ORDERS" and "ORDER_LINE". Are you sure you're not missing something from the table definition, ie: ORDER_LINE should maybe have the ORDER_ID as a FK ?
Hope this helps
You can try something like
SELECT c.*,
p.*
FROM CUSTOMER c INNER JOIN
ORDERS o ON c.Cust_ID = o.Cust_ID INNER JOIN
ORDER_LINE ol ON o.Order_ID = ol.Order_Number INNER JOIN
PART p ON ol.Part_Number = p.Part_Number
Have a look at
Join (SQL)
An SQL join clause combines records from two or more tables in a
database.
SQL Joins
The JOIN keyword is used in an SQL statement to query data from two or
more tables, based on a relationship between certain columns in these
tables.
And for some graphic examples
JOIN Basics
What you need is a simple straightforward JOIN like so:
SELECT
c.Cust_ID,
c.Name,
l.Part_Number,
l.Part_Description
FROM CUSTOMER c
INNER JOIN ORDERS o ON c.Cust_ID = o.Cust_ID
INNER JOIN ORDER_LINE ol ON o.OrdeR_ID = ol.Order_Number
INNER JOIN PART l ON ol.Part_Number = l.Part_Number
You want an SQL "join", such as:
SELECT c.Name, ol.Part_Number, p.Part_Description
FROM Customer AS c
JOIN Orders AS o ON c.Cust_ID = o.Cust_ID
JOIN Order_Line AS ol ON o.Order_ID = ol.Order_Number
JOIN Part AS p ON ol.Part_Number = p.Part_Number
Be aware that without a WHERE clause, this query will return all all parts in all orders for all customers, which will really hammer the network and perform poorly on anything but a tiny database:
WHERE (c.Cust_ID = MyCustomerID)
MySQL join syntax
SQL Server join syntax

Resources