Simple SQL query from table - sql

For my CIS class, I have SQL project, and this is the first time I'm working with SQL, doing okay but I can't do one of the queries. Any help would be greatly appreciated.
This is what I tried:
Select cno, cname
from customer
where
)
)
)

Just use two IN clauses, one for 'Financial Accounting', one for 'Cost Accounting'.
Select cno, cname
from customer
where cno in
(
select cno
from salesorder
where ono in
(
select ono
from orderline
where bno in (select bno from book where bname = 'Financial Accounting')
)
)
and cno in
(
select cno
from salesorder
where ono in
(
select ono
from orderline
where bno in (select bno from book where bname = 'Cost Accounting')
)
);
Rob M's solution is more elegant, whereas above query should be more along the lines what you've learned so far.

You aren't exactly clear on whether the customer needs to have ordered both books in one order or across multiple orders. I'll assume the latter, based on the data provided.
Your answer returns customers who ordered either (or both) of those books. You say you want customers who order both books. Also, it's hard to keep your code straight when nesting several subqueries. Most people prefer joins.
This query should work for you.
select cno,cname from customer where cno in (
select o.cno
from salesorder o
inner join orderline ol on o.ono=ol.ono
inner join book b on b.bno=ol.bno
where b.bname in ('Financial Accounting', 'Cost Accounting')
group by o.cno
having count(distinct b.bno) = 2 -- Require both separate books, not 2 of one book or the other
)
Here is a complete example in SQL Server:
declare #book table (bno int, bname varchar(50))
insert #book (bno,bname) values
(10501,'Forensic Accounting')
,(10704,'Financial Accounting')
,(10933,'Cost Accounting')
declare #orderline table (ono int, bno int)
insert #orderline (ono,bno) VALUES
(1020,10501)
,(1020,10502)
,(1020,10503)
,(1020,10504)
,(1021,10605)
,(1022,10605)
,(1022,10704)
,(1023,10879)
,(1023,10988)
,(1024,10502)
,(1024,10988)
,(1026,10933)
,(1027,10933)
,(1028,10933)
,(1028,10965)
,(1029,10933)
,(1029,10965)
,(1029,10988)
,(1030,10965)
declare #salesorder table (ono int, cno int)
insert #salesorder (ono,cno) VALUES
(1020,23511)
,(1021,23513)
,(1022,23513)
,(1023,23512)
,(1024,23511)
,(1025,23511)
,(1026,23511)
,(1027,23512)
,(1028,23512)
,(1029,23513)
,(1030,23511)
declare #customer table (cno int, cname varchar(20))
insert #customer (cno,cname) values
(23511,'a')
,(23512,'b')
,(23513,'c')
,(23514,'d')
,(23515,'e')
,(23516,'f')
,(23517,'g')
,(23518,'h')
select cno,cname from #customer where cno in (
select o.cno
from #salesorder o
inner join #orderline ol on o.ono=ol.ono
inner join #book b on b.bno=ol.bno
where b.bname in ('Financial Accounting', 'Cost Accounting')
group by o.cno
having count(distinct b.bno) = 2 -- Require both separate books, not 2 of one book or the other
)

Related

Sql query to find select customer that bought in the specific company address

Here is my table
CREATE TABLE Customer
(
ID CHAR(50),
Customer_FName CHAR(50),
Customer_Lname CHAR(50)
);
CREATE TABLE Buying
(
Customer_ID CHAR(50),
Product_ID CHAR(50),
Order_Time CHAR(50)
);
CREATE TABLE Product
(
ID CHAR(50),
Name CHAR(50),
Address CHAR(50)
);
I am trying to find all customers who bought a product with their company's address in 'Burwood' and list the customer's ID, names, product ID, product name and product address
Select
Buying.Customer_ID, Buying.Product_ID, Product.ID,
Product.Name, Customer.ID,
Customer.Customer_FName, Customer.Customer_Lname
from
((Buying
inner join
Product on Buying.Product_ID = Product.ID)
inner join
Customer on Buying.Customer_ID = Customer.ID)
where
Product.Address like '%Burwood%';
I want to combine three table but It shows 'no rows selected'.
I also give a sample data table
Any reason why you have chosen CHAR as the datatype for all columns of all tables? For CHAR based columns, DBs tend to pad the values up to the column width defined. That said, it is not why you are not getting result. You may want to check if during insert you are adding any extra space or non-printable characters in IDs resulting into failed inner joins.
I suggest change the fields to VARCHAR instead, validate your inserts and then query just as I demonstrated below. You will start getting result, as I am..
CREATE TABLE Customer (
ID varchar(50),
Customer_FName varchar(50),
Customer_Lname varchar(50)
);
CREATE TABLE Buying (
Customer_ID varchar(50),
Product_ID varchar(50),
Order_Time varchar(50)
);
CREATE TABLE Product (
ID varchar(50),
Name varchar(50),
Address varchar(50)
);
insert into customer values('10001', 'John', 'Smith');
insert into Buying values('10001', '772', '2016/09/01');
insert into Product values('772', 'Telephone', '22 Ave, Burwood');
select b.product_id, p.name, b.customer_id, c.customer_fname, c.customer_lname
from buying b
join product p on b.product_id = p.id
join customer c on b.customer_id = c.id
where lower(p.address) like '%burwood%'
Please try this, it works for me:
Select B.Customer_ID, B.Product_ID, P.ID, P.Name, C.ID, C.Customer_FName, C.Customer_Lname
from Buying B
INNER JOIN Product P ON B.Product_ID = P.ID
INNER JOIN Customer C ON B.Customer_ID = C.ID
WHERE P.Address LIKE '%Burwood%'
Try this:
SELECT C.*,B.*, P.*
FROM Customer C,Buying B, Product P
WHERE B.Product_ID=P.ID
AND B.Customer_ID=C.ID
AND P.Address LIKE '%Burwood%';

What is "master join" in sql

CREATE TABLE car (id INT, name1 CHAR(15))
CREATE TABLE sales (sid INT, cid INT, year1 INT)
INSERT INTO car
VALUES (1, 'vento'), (2, 'vento'), (3, 'baleno'), (4, 'swift')
INSERT INTO sales
VALUES (1, 1, 2017), (2, 3, 2018), (3, 3, 2017), (5, 4, 2017)
--verify
--SELECT * FROM car
--SELECT * FROM sales
--1st query
SELECT sid, cid, year1, name1
FROM sales master
INNER JOIN car ON cid = id
--2nd query
SELECT sid, cid, year1, name1
FROM sales
INNER JOIN car ON cid = id
What is the difference between the 1st and the 2nd query?
What is the purpose of "master join" and when should we use it?
Nothing is different, it is functionally the same.
To explain, I've qualified the column names to demonstrate that master is just an alias.
I'd highly recommend qualifying the rest of the query as well, since ...car on cid = id works now, but isn't good form because if ever sales or car tables had the same column name, you'd get an error about ambiguity.
Also, decide if you want to use INNER JOIN, LEFT OUTER JOIN, etc.. [Types of joins] because it's more clear what you desire from a maintenance point of view later on.
SELECT master.sid
,master.cid
,master.year1
,c.name1
FROM sales master
INNER JOIN car c ON master.cid = c.id --(1st)
SELECT s.sid
,s.cid
,s.year1
,c.name1
FROM sales s
INNER JOIN car c ON s.cid = c.id --(2nd)
There is no concept called Master Join in sql.
SELECT
sid, cid, year1, name1
FROM sales master
INNER JOIN car
ON
cid = id
The above query takes master as alias name for sales table and does the inner join between sales table and car table
you can refer cid using alias (master) as below:
SELECT
sid, cid, year1, name1
FROM sales master
INNER JOIN car
ON
master.cid = id

Select multiple columns from another table depending on value of column

I'm not even sure this is possible, but I have an order table (online store). Within this table, the shipping and billing address columns are ID's which correspond with the address table.
For E.g.
OrderID ShippingAddressID BillingAddressID
201800194 21183 21182
The Address table then lists the address information.
AddressID Address1 City RegionCode
21182 123 Somewhere Dr Hometown1 Florida
21183 456 Elsewhere Rd Hometown2 Florida
I'd like the resulting listing to show something similar to this:
OrderID BillingAddress1 BillingCity BillingRegionCode ShippingAddress1 ShippingCity ShippingRegionCode
201800194 123 Somewhere Dr Hometown1 Florida 456 Elsewhere Rd Hometown2 Florida
Is this even possible?
Thanks..
Join the address table twice. Example with your data below.
CREATE TABLE #Orders (OrderID int, ShippingAddressId int, BillingAddressId int)
CREATE TABLE #Address (AddressID int, Address1 varchar(100), City varchar(100), RegionCode varchar(100))
INSERT INTO #Orders (OrderID, ShippingAddressId, BillingAddressId) VALUES
(201800194 , 21183, 21182)
INSERT INTO #Address (AddressID, Address1, City, RegionCode) VALUES
(21182, '123 Somewhere Dr', 'Hometown1', 'Florida'),
(21183, '456 Elsewhere Rd', 'Hometown2', 'Florida')
SELECT
ORD.OrderID,
BILL.Address1 AS 'BillingAddress1',
BILL.City AS 'BillingCity',
BILL.RegionCode AS 'BillingRegionCode',
SHIP.Address1 AS 'ShippingAddress1',
SHIP.City AS 'ShippingCity',
SHIP.RegionCode AS 'ShippingRegionCode'
FROM
#Orders AS ORD
LEFT OUTER JOIN #Address AS SHIP
ON ORD.ShippingAddressId = SHIP.AddressID
LEFT OUTER JOIN #Address AS BILL
ON ORD.BillingAddressId = BILL.AddressID
DROP TABLE #Orders
DROP TABLE #Address
Lets assume your Tables are Order, Address.
Select A.OrderID, B1.Address1 As 'BillingAddress1', B1.City As 'BillingCity', B1.RegionCode As 'BillingRegionCode', B2.Address1 As 'ShippingAddress1', B2.City As 'ShippingCity', B2.RegionCode As 'ShippingRegionCode'
FROM Order AS A
Left Join Address AS B1 On A.BillingAddressID = B1.AddressID
Left Join Address As B2 On A.ShippingAddressID = B2.AddressID
Hope this Helps
Yes you can achieve it using join like this -
SELECT OrderId, Billing.Address1 As BillingAddress1, Shipping.Address1 AS
ShippingAddress1, ... other column
FROM dbo.Order
LEFT JOIN dbo.Address AS Billing ON Order.BillingAddressID = Billing.AddressID
LEFT JOIN dbo.Address AS Shipping ON Order.ShippingAddressID = Shipping.AddressID

inner join and partial matches

I'm not sure if the title's correct, so here goes.
The following script returns the correct result: currently Roy Brown teaches Math 101. Roy Brown's TeacherID is 1225, but then they later added the prefix 001- for other purposes.
What I would like to include in the result is some identification that Roy Brown did have another course at one point in time, since Math 101 Old has 1225. It doesn't even have to show how many other courses he had; just something that will let me know that there is more than one row in #coursesCsv. But the result should remain to 2 rows.
What I don't want is to display an extra row for Roy Brown, which is why I'm not doing the commented inner join (ie. right(t.teacherid,4) = right(c.teacherid,4)).
There are no relationships between these two tables since the data in #coursesCSV comes from a csv file.
IF OBJECT_ID('tempdb..#teacher') IS NOT NULL DROP TABLE #teacher
IF OBJECT_ID('tempdb..#coursesCsv') IS NOT NULL DROP TABLE #coursesCsv
create table #teacher
(
TeacherID varchar(10),
FullName varchar(30)
)
insert into #teacher select '001-1225', 'Roy Brown'
insert into #teacher select '001-1230', 'Woody Boyd'
create table #coursesCsv
(
CourseName varchar(30),
TeacherID varchar(10)
)
insert into #coursesCsv select 'Math 101', '001-1225'
insert into #coursesCsv select 'Math 101 Old', '002-1225'
insert into #coursesCsv select 'History 101', '001-1230'
select t.teacherid, c.coursename from
#teacher t inner join #coursesCsv c
on t.teacherid = c.teacherid
--on right(t.teacherid,4) = right(c.teacherid,4)
Do a "Group Count" of courses for the same right(teacherid,4) within a Derived Table (or a Common Table Expression = WITH) and join to it:
select t.teacherid, c.coursename, c.coursecnt
from teacher t
inner join
(
select
teacherid,
coursename,
count(*)
over (partition by right(teacherid,4)) as coursecnt
from coursesCsv
) as c
on t.teacherid = c.teacherid

Removing Duplicate values within a Query when Distinct doesn't work? SQL

Here is the current query I am running.
select c.customer_name, c.city, c.credit_limit, sum(ol.quoted_price)
from customer c, order_line ol, (select order_num from order_line where part_num = 'AT94') t1
where ol.order_num = t1.order_num and customer_num in ( select customer_num
from orders
where order_num in (select t1.order_num
from order_line,(select order_num from order_line where part_num = 'AT94') t1
INNER JOIN
(select order_num from order_line where part_num = 'BV06') t2
on t1.order_num = t2.order_num
where t1.order_num = order_line.order_num
group by t1.order_num))
group by t1.order_num, c.customer_name, c.city, c.credit_limit
The current output I am receiving is:
I wish to obviously remove the duplication located in the output and currently have no idea how to do so. I have tried using unique in the multiple sub-queries with no success.
Any help is great! Thanks.
Here is the database creation.
CREATE TABLE CUSTOMER
(
CUSTOMER_NUM CHAR(3) PRIMARY KEY,
CUSTOMER_NAME CHAR(35) NOT NULL,
STREET CHAR(15),
CITY CHAR(15) DEFAULT 'Ottawa',
PROVINCE CHAR(3),
ZIP CHAR(5),
BALANCE DECIMAL(8,2),
CREDIT_LIMIT DECIMAL(8,2),
REP_NUM CHAR(2)
CONSTRAINT CHK_Limit CHECK (CREDIT_LIMIT >= BALANCE)
);
CREATE TABLE ORDERS
(
ORDER_NUM CHAR(5) PRIMARY KEY,
ORDER_DATE DATE,
CUSTOMER_NUM CHAR(3)
);
CREATE TABLE PART
(
PART_NUM CHAR(4) PRIMARY KEY,
DESCRIPTION CHAR(15),
ON_HAND DECIMAL(4,0),
CLASS CHAR(2),
WAREHOUSE CHAR(1),
PRICE DECIMAL(6,2)
);
CREATE TABLE ORDER_LINE
(
ORDER_NUM CHAR(5),
PART_NUM CHAR(4),
NUM_ORDERED DECIMAL(3,0),
QUOTED_PRICE DECIMAL(6,2),
PRIMARY KEY (ORDER_NUM, PART_NUM)
);
The solution I would like where the order does not matter for the column:
Al's.. | Barrhaven | 7500.00 | 21.95
John.. | Toronto | 10000.00 | 311.95
All data used. Quite a large sum of text. Just decided Pastebin instead of making this question that much longer.
https://pastebin.com/ASBzqcJq
You basically need to see which customer has bought both of parts_numb AT94 and BV06. The issue you're facing is that your query returning duplicated rows, this is because your query already have some redundancy. Which made me go back and check the giving results manually to get the correct results out of the sample that you've provided.
SELECT
ol.ORDER_NUM,
c.customer_name,
c.city,
c.credit_limit,
sum(ol.quoted_price)
FROM #order_line ol
INNER JOIN #Orders o ON o.order_num = ol.order_num
JOIN (SELECT ORDER_NUM FROM #ORDER_LINE WHERE part_num = 'AT94') t1 ON t1.ORDER_NUM = o.ORDER_NUM
JOIN (SELECT ORDER_NUM FROM #ORDER_LINE WHERE part_num = 'BV06') t2 ON t2.ORDER_NUM = o.ORDER_NUM
INNER JOIN #customer c ON c.customer_num = o.customer_num
WHERE
ol.ORDER_NUM IN(t1.ORDER_NUM)
AND ol.ORDER_NUM IN(t2.ORDER_NUM)
GROUP BY
ol.ORDER_NUM,
c.customer_name,
c.city,
c.credit_limit
SQLFiddle
Hope this will save your day
I can see that your result set already has distinct records. Your result set does not have any two rows with exactly same values. What is the output you are expecting? I am not sure what your requirement is. But I think the join between customer number in Customer table and Customer number in Orders table is missing.
Are you trying to do something like this?
select C.customer_name, C.city, C.credit_limit, sum(OL.quoted_price)
from CUSTOMER C
join ORDERS O ON C.Customer_num=O.Customer_num
join ORDER_LINE OL on O.Order_num=Ol.Order_num
WHERE part_num in('AT94','BV06')
group by C.customer_name, C.city, C.credit_limit;