Returning multiple aggregate functions as rows - sql

I need some help formulating a select statement. I need to select the total quantity shipped for each part with a distinct color. So the result should be a row with the color name and the total.
Here's my schema:
create table s
( sno char(5) not null,
sname char(20) not null,
status smallint,
city char(15),
primary key (sno)
);
create table p
( pno char(6) not null,
pname char(20) not null,
color char(6),
weight smallint,
city char(15),
primary key (pno)
);
create table sp
( sno char(5) not null,
pno char(6) not null,
qty integer not null,
primary key (sno, pno)
);

As your schema stands each product PNO has only one colour, so I'm not sure what your question actually requires.
Sales by product:
select p.pno
, sum (sp.qty)
from p join sp on (p.pno = sp.pno)
group by p.pno;
Sales by colour:
select p.color
, sum (sp.qty)
from p join sp on (p.pno = sp.pno)
group by p.color;
edit
To get sales for a specific colour is easy:
select sum (sp.qty)
from p join sp on (p.pno = sp.pno)
where p.color = 'BLUE';

Related

get data from related tables in postgresql

assuming these 3 tables
create table item(
item_id integer NOT NULL primary key,
name varchar(50) NOT NULL,
description varchar(150) NOT NULL,
in_stock integer NOT NULL
)
create table customer(
customer_id VARCHAR(9) NOT NULL primary key,
name VARCHAR(50) NOT NULL,
lastname VARCHAR(50) NOT NULL,
phone VARCHAR(15) NOT NULL,
join_date DATE NOT NULL
)
create table purchase(
purchase_id integer references item,
customer_id varchar(9) references customer,
purchase_date TIMESTAMP NOT NULL,
amount INTEGER NOT NULL,
PRIMARY KEY(purchase_id, customer_id, purchase_date)
)
how could I get each unique name and the total amount of items purchased?
how could I get each purchase name and the buyer's name and lastname?
how could I get each item and how many of it were sold?
The two topics you are looking to learn are how to use GROUP BY and how to JOIN tables. Here's an example (more or less) that answers your first question and uses both tools:
select
C.customer_id as customer_id,
max(C.name) as customer_name,
sum(amount) as total_amount
from customer C
left join purchase P on C.customer_id = P.customer_id
group by C.customer_id

Ambiguous column name 'ProductNumber'

Can't figure out why my question 3 is getting the error mentioned above.
Below is my code
/* Question 1 */
CREATE TABLE CUSTOMERS
(
CustomerID INT PRIMARY KEY,
CustFirstName VARCHAR(50) NOT NULL,
CustLastName VARCHAR(50) NOT NULL,
CustStreetAddress VARCHAR(50) NOT NULL,
CustCity VARCHAR(50) NOT NULL,
CustState VARCHAR(26) NOT NULL,
CustZipCode INT NOT NULL,
CustAreaCode INT NOT NULL,
CustPhoneNumber VARCHAR (26) NOT NULL
);
CREATE TABLE EMPLOYEES
(
EmployeeID INT PRIMARY KEY,
EmpFirstName VARCHAR(50) NOT NULL,
EmpLastName VARCHAR(50) NOT NULL,
EmpCity VARCHAR (50) NOT NULL,
EmpState VARCHAR(26) NOT NULL,
EmpZipCode INT NOT NULL,
EmpAreaCode INT NOT NULL,
EmpPhoneNumber VARCHAR(26) NOT NULL,
EmpBirthDate DATE NOT NULL
);
CREATE TABLE ORDERS
(
OrderNumber INT PRIMARY KEY,
OrderDate DATE NOT NULL,
ShipDate DATE NOT NULL,
CustomerID INT NOT NULL,
EmployeeID INT NOT NULL,
FOREIGN KEY(EmployeeID) REFERENCES EMPLOYEES(EmployeeID),
FOREIGN KEY(CustomerID) REFERENCES CUSTOMERS(CustomerID)
);
CREATE TABLE CATEGORIES
(
CategoryID INT PRIMARY KEY,
CategoryDescription VARCHAR(255) NOT NULL
);
CREATE TABLE PRODUCTS
(
ProductNumber INT PRIMARY KEY,
ProductName VARCHAR(50) NOT NULL,
ProductDescription VARCHAR(255) NOT NULL,
RetailPrice INT NOT NULL,
QuantityOnHand INT NOT NULL,
CategoryID INT NOT NULL,
FOREIGN KEY(CategoryID) REFERENCES CATEGORIES (CategoryID)
);
CREATE TABLE ORDER_DETAILS
(
OrderNumber INT NOT NULL,
ProductNumber INT NOT NULL,
QuotedPrice INT NOT NULL,
QuantityOrdered INT NOT NULL,
PRIMARY KEY (OrderNumber, ProductNumber),
FOREIGN KEY (OrderNumber) REFERENCES ORDERS(OrderNumber),
FOREIGN KEY(ProductNumber) REFERENCES PRODUCTS(ProductNumber)
);
CREATE TABLE VENDORS
(
VendorID INT PRIMARY KEY,
VendName VARCHAR(100) NOT NULL,
VendStreetAddress VARCHAR(50) NOT NULL,
VendCity VARCHAR(50) NOT NULL,
VendState VARCHAR(26) NOT NULL,
VendFaxNumber VARCHAR(50) NOT NULL,
VendWebPage VARCHAR(100) NOT NULL,
VendEmailAddress VARCHAR(100) NOT NULL
);
CREATE TABLE PRODUCT_VENDORS
(
ProductNumber INT NOT NULL,
VendorID INT NOT NULL,
WholeSalePrice INT NOT NULL,
DaysToDeliver INT NOT NULL,
PRIMARY KEY(ProductNumber, VendorID),
FOREIGN KEY(ProductNumber) REFERENCES PRODUCTS(ProductNumber),
FOREIGN KEY(VendorID) REFERENCES Vendors(VendorID)
);
/* QUESTION 2 */
SELECT
OrderDate, CustFirstName, CustLastName
FROM
CUSTOMERS C, ORDERS O
WHERE
C.CustomerID = O.OrderNumber;
/* QUESTION 3 */
SELECT
ProductNumber, WholeSalePrice, VendName
FROM
PRODUCTS P, PRODUCT_VENDORS PV, VENDORS V
WHERE
P.PRODUCTNUMBER = PV.ProductNumber AND PV.VendorID = V.VendorID;
I got the error
Ambiguous column name 'ProductNumber'
Because there are two table have column name of ProductNumber in your query you need to tell DB engine which column you want to get.
Also, use JOIN instead of , comma CROSS JOIN, because Join is more clear than a comma on the relationship between the two tables
SELECT PV.ProductNumber, WholeSalePrice, VendName
FROM PRODUCTS P
JOIN PRODUCT_VENDORS PV ON P.PRODUCTNUMBER = PV.ProductNumber
JOIN VENDORS V ON PV.VendorID = V.VendorID;
Your query stipulates SELECT ProductNumber From two tables that both have ProductNumber. In the SELECT columns list, prefix ProductNumber with the table name from which you want to receive the data.
also, Have a look at your question 2. I don't think you really want to join customer id to order number, and you should use JOIN syntax intead of joining in the WHERE clause
Ambiguous error means that you are calling a certain field in which exist in both Table and the SQL has no idea where to get it. See, with your query, you're just literally calling the ProductNumber field in which the SQL has no idea where to get it since there are ProductNumber fields on both Tables, and you didn't specify any table.
so it is better when you have same column in multiple tables use table preface 1st then column like table1.col1,table2.col2
so in your case
SELECT p.ProductNumber, WholeSalePrice, v.VendName
FROM PRODUCTS P join
PRODUCT_VENDORS PV on P.PRODUCTNUMBER = PV.ProductNumber //
join VENDORS V on PV.VendorID = V.VendorID //use join instead your's

Get count of games and display the players who played half of games

i Need help in these tables, i want SQL statement to give me this :
the players who played in half or more of the games, lets assume that we have 6 different games in 'GameType' table ... So I want to display all players who played 3 or more games.
like :
ID surName number of games played
1 test1 3
2 test2 4
3 test3 3
4 test4 6
this what i done until now:
SELECT dbo.Player.ID, dbo.Player.surName, count(DISTINCT
dbo.PlayerInAGame.gameTypeName) AS games_played, count(DISTINCT
dbo.Game.gameTypeName) AS games_count
FROM dbo.Player INNER JOIN
dbo.PlayerInAGame ON dbo.Player.ID =
dbo.PlayerInAGame.playerID INNER JOIN
dbo.Game ON dbo.PlayerInAGame.gameTypeName = dbo.Game.gameTypeName AND
dbo.PlayerInAGame.gameDateTime = dbo.Game.gameStartDateTime
GROUP BY dbo.Player.ID, dbo.Player.surName, dbo.Game.DealerInGame
here is the tables:
create table Dealer
(
number int identity(1000,1) primary key,
firstName nvarchar(20) not null,
surName nvarchar(20) not null,
birthDate date not null,
startWorkingDate date not null,
ID char(9) check(ID like replicate('[0-9]',9)) not null unique,
check(datediff(year,birthDate,startWorkingDate)>=24)
)
create table GameType
(
name nvarchar(20) primary key,
description nvarchar(20) not null,
minimumPlayers tinyint check (minimumPlayers > 0) not null,
maximumPlayers tinyint check (maximumPlayers > 0) not null,
check(minimumPlayers <= maximumPlayers)
)
create table Game
(
gameTypeName nvarchar(20) references GameType(name) on delete cascade,
gameStartDateTime datetime,
gameEndTime time,
DealerInGame int not null references Dealer(number),
primary key(gameTypeName,gameStartDateTime)
)
create table Player
(
ID char(9) primary key,
firstName nvarchar(20) not null,
surName nvarchar(20) not null,
city nvarchar(20) not null,
birthDate date check(datediff(year,birthDate,getdate())>=18) not null,
preferred nvarchar(20) references GameType(name) on delete set null
)
create table PlayerInAGame
(
playerID char(9) references Player(ID),
gameTypeName nvarchar(20),
gameDateTime datetime,
betAmount int check(betAmount>0) not null,
winLosAmount int,
check((winLosAmount = -betAmount) or (winLosAmount>=betAmount)),
foreign key(gameTypeName,gameDateTime) references
Game(gameTypeName,gameStartDateTime), primary
key(playerID,gameTypeName,gameDateTime) )
create table PlayerDealerRelation
(
dealerNumber int references Dealer(number) on delete cascade,
playerID char(9) references Player(ID),
relationType char(1) check(relationType in ('P','G','B','C','U','N')),
primary key(dealerNumber,playerID)
)
If your query in the question gives you the correct count, then it is very easy to add an extra filter that would leave only those rows where games_played is more than half of games_count.
Just add HAVING:
SELECT
dbo.Player.ID,
dbo.Player.surName,
count(DISTINCT dbo.PlayerInAGame.gameTypeName) AS games_played,
count(DISTINCT dbo.Game.gameTypeName) AS games_count
FROM
dbo.Player
INNER JOIN dbo.PlayerInAGame ON dbo.Player.ID = dbo.PlayerInAGame.playerID
INNER JOIN dbo.Game
ON dbo.PlayerInAGame.gameTypeName = dbo.Game.gameTypeName
AND dbo.PlayerInAGame.gameDateTime = dbo.Game.gameStartDateTime
GROUP BY dbo.Player.ID, dbo.Player.surName, dbo.Game.DealerInGame
HAVING
count(DISTINCT dbo.PlayerInAGame.gameTypeName) >
count(DISTINCT dbo.Game.gameTypeName) / 2

SQL queries - For Customer and Sale representative

Q: List the numbers and names of all customers who are represented by Ann Hull but who do not currently have orders on file.
This is what I have so far... but it isn't the right output:
CREATE TABLE REP (
REP_NUM char(2) PRIMARY KEY,
LAST_NAME char(15),
FIRST_NAME char(15),
STREET char(15),
CITY char(15),
PROVINCE char(3),
ZIP char(5),
COMMISSION decimal(7, 2),
RATE decimal(3, 2)
);
CREATE TABLE CUSTOMER (
CUSTOMER_NUM char(3) PRIMARY KEY,
CUSTOMER_NAME char(35) NOT NULL,
STREET char(15),
CITY char(15),
PROVINCE char(3),
ZIP char(5),
BALANCE decimal(8, 2),
CREDIT_LIMIT decimal(8, 2),
REP_NUM char(2)
);
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)
);
SELECT * FROM CUSTOMER c
LEFT JOIN REP r
ON c.REP_NUM = r.REP_NUM
LEFT JOIN ORDERS o
ON o.CUSTOMER_NUM = c.CUSTOMER_NUM
WHERE o.CUSTOMER_NUM ISNULL
AND r.FIRST_NAME = 'Ann Hull'
Hope the above helps, It should work with minor modifications to the where clause especially combining the first and last names.
Filter the Rep table on firstname and lastname for Ann Hull and join it with the Rep table on the rep_num fields. To only return customers with no orders use a subquery to check that no orders exists (NOT EXISTS) in the Order table for a customer.
SELECT * FROM CUSTOMER c
JOIN REP r
ON c.REP_NUM = r.REP_NUM
AND r.FIRSTNAME = 'Ann'
AND r.LASTNAME = 'Hull'
AND NOT EXISTS(SELECT * FROM ORDERS o WHERE o.CUSTOMER_NUM = c.CUSTOMER_NUM)

SQL Server : Conditional Sort with Multiple Columns

I am having an issue with a conditional sort in SQL Server. I have a lengthy procedure that in the end produces a list of magazine subscriptions that are up for renewal. This is the basic structure of the end result table:
create table #renewals
(
product_no integer NULL,
quantity integer NULL,
order_date datetime NULL,
order_no integer NULL,
customer_no varchar(10) NULL,
description varchar(50) NULL,
first_name varchar(30) NULL,
middle_name varchar(30) NULL,
last_name varchar(30) NULL,
salute varchar(5) NULL,
acct_no char(8) NULL,
contact_type varchar(8) NULL,
contact_no integer NULL,
line_item int,
edition_code char(3) NULL
)
The issue lies in the multi-level sort that I am trying to accomplish. In the end, I need this data sorted by edition_code ASC which is simple enough.
However, some editions have add-on products which then need to be inserted underneath the correct edition_code. This is where I am running into a problem. An example of a regular edition code is 002 or 014. The add-on edition codes are 300, 302, etc. If I only sort by edition_code then all of the add-on editions get moved to the bottom of the list.
The following is a rundown of the result set:
product_no -- This is a different number than edition_code, but same principal
quantity -- self-explanatory
order_date -- self-explanatory
order_no -- For each unique result set, this number is the same
customer_no -- this is unique for each customer and helps to bundle main editions with their add-ons
description -- title of edition
first (through) last_name -- self-explanatory
salute -- self-explanatory
acct_no -- For each result set, this number is the same because all the customers will belong to the same account (think multiple doctors subscribing to a magazine but all work out of the same hospital)
contact_type -- PK
contact_no -- PK
line_item -- line number when entered on order (this does not help with sorting at all)
edition_code -- Unique code for an edition of our product
Below is the result I am expecting:
Customer_1 | Edition_1
Customer_2 | Edition_1
Customer_2 | Add-On_1
Customer_2 | Add-On_2
Customer_9 | Edition_1
Customer_6 | Edition_2
Customer_5 | Edition_2
Customer_5 | Add-On_2
Customer_3 | Edition_3
The closest I can get is by simply sorting by customer_no which will put the add-ons with their editions (You cannot order an add-on without ordering the main edition), but this does not sort by main edition code, which is what the overall (main) sort should accomplish.
This is the procedure that produces the result, not sure how it'll help:
CREATE TABLE #renewals
(
product_no integer NULL,
quantity integer NULL,
order_date datetime NULL,
order_no integer NULL,
customer_no varchar(10) NULL,
description varchar(50) NULL,
first_name varchar(30) NULL,
middle_name varchar(30) NULL,
last_name varchar(30) NULL,
salute varchar(5) NULL,
acct_no char(8) NULL,
contact_type varchar(8) NULL,
contact_no integer NULL,
line_item int,
edition_code char(3) NULL
)
INSERT INTO #renewals
(
product_no,
quantity,
order_date,
order_no,
customer_no,
description,
first_name,
middle_name,
last_name,
salute,
acct_no,
contact_type,
contact_no ,
line_item,
edition_code
)
SELECT
product.product_no,
order_table_1.quantity,
order_table_1.order_date,
order_table_1.order_no,
order_table_1.customer_no,
product.description,
isnull(customer_table_1.first_name, ''),
isnull(customer_table_1.middle_name, ''),
isnull(customer_table_1.last_name, ''),
isnull(customer_table_1.salute, ''),
order_table_1.acct_no,
'',
-1,
line_item_no,
order_table_1.edition_code
FROM order_table_1
LEFT OUTER JOIN product ON order_table_1.edition_code = product.edition_code
LEFT OUTER JOIN customer_table_1 ON order_table_1.customer_no = customer_table_1.customer_no AND order_table_1.acct_no = customer_table_1.acct
WHERE
(order_table_1.acct_no = #acct) AND
(order_table_1.school_year = #school_year) AND
(order_table_1.edition_code <> '065') AND
(order_table_1.status_code in ('E','A','F')) AND
(isnull(order_table_1.renewed,'N') <> 'Y')
UPDATE o
SET o.first_name = isnull(tc.first_name, ''),
o.middle_name = isnull(tc.middle_name, ''),
o.last_name = isnull(tc.last_name, ''),
o.salute = isnull(tc.salute, ''),
o.contact_type = tc.contact_type,
o.contact_no = tc.contact_no
FROM #renewals o, accounts ta, contacts tc
WHERE
(o.acct_no = ta.acct) AND
(ta.acct_type = tc.acct_type) AND
(ta.acct_no = tc.acct_no) AND
(o.customer_no = tc.customer_no) AND
(o.customer_no is not null) AND
(o.customer_no <> '') AND
(o.customer_no not like '999999999%')
SELECT
cast(o.product_no as int) as 'product_no',
o.quantity,
o.order_date,
o.order_no,
o.customer_no,
o.description,
o.first_name,
o.middle_name,
o.last_name,
o.salute,
o.acct_no,
o.contact_type,
o.contact_no,
o.line_item,
o.edition_code
FROM #renewals o
ORDER BY o.edition_code
You can't sort what you don't have. You need a table of edition_code, addon_code pairs. Then join to that table with
#renewals.edition_code in (X.edition_code, X.addon_code)
...
order by X.edition_code, X.addon_code
I'm making a few assumptions: that the two code sets don't overlap, that edition_code is always less than addon_code, and that you want the addons ordered by their code. Sometimes in cases like this a third column is required to express the sort order.