How to SELECT titles by sales, where sales less than N? - sql

I have 2 tables: titles and sales created by queries:
CREATE TABLE [dbo].[sales]
(
[stor_id] [char] (4) NOT NULL,
[ord_num] [varchar] (20) NOT NULL,
[ord_date] [datetime] NOT NULL,
[qty] [smallint] NOT NULL, --quantity of sold books in this transaction
[payterms] varchar(12) NOT NULL,
[title_id] varchar(6) NOT NULL, --FOREIGN KEY REFERENCES titles(title_id),
CONSTRAINT FK_S_title_id
FOREIGN KEY (title_id) REFERENCES titles(title_id),
CONSTRAINT PK_sales
PRIMARY KEY CLUSTERED (stor_id, ord_num, title_id)
) ON [PRIMARY]
CREATE TABLE [dbo].[titles]
(
[title_id] varchar(6) CONSTRAINT PK_titles PRIMARY KEY CLUSTERED,
[title] varchar(80) NOT NULL, --name of book
[type] char(12) NOT NULL DEFAULT ('UNDECIDED'),
[pub_id] char(4) NULL,
[price] money NULL,
[advance] money NULL,
[royalty] int NULL,
[ytd_sales] int NULL,
[notes] varchar(200) NULL,
[pubdate] datetime NOT NULL DEFAULT (getdate())
) ON [PRIMARY]
I know that I can get a table of pairs title and sumOfSales by this query
SELECT title, SUM(qty) AS sumOfSales
FROM titles AS t, sales AS s
WHERE t.title_id = s.title_id
GROUP BY title
ORDER BY title
It results as this:
But I need to select all titles that are sold less or equal than 10 times and get something like this, without qty (nor sumOfSales) column:
title
=======================================
ABookThatIsSoldLessOrEqual10Times
NameOfAnotherBookSoldLessOrEqual10times
NameOfBookSoldLessOrEqual10times
EDIT: Thank you for answers. I wanted to use HAVING, but it doesn't do what I need to have in result of SELECT. I need to have a list of just titles of books that are sold only 10 or less times.
I could use a temporary table and do 2 SELECTs instead of one. But it is not very good practice.

AS you need to show a list of just titles of books then try this:
SELECT title FROM titles AS t inner join sale AS s
on t.title_id = s.title_id
GROUP BY title
HAVING sum(qty) <= 10
ORDER BY title

Use HAVING clause:
SELECT title, SUM(qty) AS sumOfSales
FROM titles AS t, sales AS s
WHERE t.title_id = s.title_id
GROUP BY title
HAVING SUM(qty) < 11
ORDER BY title
You can write the condition as SUM(qty) <= 10 if you like, but I find SUM(qty) < 11 more elegant.

You need to add HAVING to your query
SELECT title, sum(qty) AS sumOfSales
FROM
titles AS t
INNER JOIN sales AS s ON t.title_id = s.title_id
GROUP BY title
HAVING sum(qty) <= 10
ORDER BY title

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

SQL Cross table/Pivot table for orders and products

I have an 'Orders' table that looks like this:
CREATE TABLE [dbo].[Orders] (
[OrderID] INT IDENTITY (1, 1) NOT NULL,
[DatePurchase] DATETIME NOT NULL,
[Quantity] INT NOT NULL,
[TotalPrice] REAL NOT NULL,
[ProductID] INT NOT NULL,
[MemberID] INT NOT NULL,
PRIMARY KEY CLUSTERED ([OrderID] ASC),
FOREIGN KEY ([ProductID]) REFERENCES [dbo].[Product] ([ProductID]),
FOREIGN KEY ([MemberID]) REFERENCES [dbo].[Member] ([MemberID])
);
I want to create a pivot table query that is able to show the the amount of orders for each product that uses the products names as the column headers (which is Product.Name from the Product table).
Example data:
Orders table:
OrderID Date Quantity TotalPrice ProductID MemberID
1 22/11/2017 00:00:00 3 39 14 27
Products table:
ProductID Price Name
11 13 Shorts
Example output:
Shorts Top Trousers
Orders 2 3 1
I have tried looking around but just can't get my head around these types of queries, can anyone help me out?

MSSQL Query for my chat site not working. Please look into it

I am building a chat site and for presenting the chats to the audiences, I have 3 Dropdownlists - Sports (Default is All Sports), Day/Month/Year, Users online/Total Users.
Now, if by default all sports is selected and I pick 1 month and Total users, the expected result should be
Chatroom name Total Users Online users
Basketball
Roomname27 32 5
Roomname11 15 3
Roomname32 8 1
Football
Roomname5 63 12
Roomname18 44 7
Roomname4 15 2
My query is
SELECT DISTINCT roo.[Sports],
roo.[Name],
COUNT(DISTINCT chu.ChatUserLogId) AS TotalUsers,
COUNT(DISTINCT liu.[LoggedInUserID]) AS UserOnline
FROM Room AS roo
LEFT JOIN LoggedInUser AS liu ON roo.RoomID = liu.RoomID
LEFT JOIN ChatUserLog AS chu ON roo.RoomID = chu.RoomID
AND chu.LoggedInTime >= DATEADD(DAY,-30,GETDATE())
GROUP BY roo.[Sports], roo.[Name]
ORDER BY TotalUsers DESC
And the table and their columns are as follows
CREATE TABLE [dbo].[Room] (
[RoomID] INT IDENTITY (6666, 1) NOT NULL,
[Name] VARCHAR (100) NOT NULL,
[Sports] VARCHAR (50) NOT NULL,
[CreatedDate] DATETIME DEFAULT (getdate()) NOT NULL,
[CreatedBy] VARCHAR (50) NOT NULL,
[CreatedUserID] INT NOT NULL,
PRIMARY KEY CLUSTERED ([RoomID] ASC)
);
CREATE TABLE [dbo].[ChatUserLog] (
[ChatUserLogId] BIGINT IDENTITY (1, 1) NOT NULL,
[MId] INT NOT NULL,
[RoomId] INT NOT NULL,
[LoggedInTime] DATETIME DEFAULT (getdate()) NOT NULL,
[LogOutTime] DATETIME DEFAULT (getdate()) NULL,
PRIMARY KEY CLUSTERED ([ChatUserLogId] ASC)
);
CREATE TABLE [dbo].[LoggedInUser] (
[LoggedInUserID] INT IDENTITY (1, 1) NOT NULL,
[MId] INT NOT NULL,
[RoomID] INT NOT NULL,
[NickName] VARCHAR (50) NOT NULL,
[Icon] VARCHAR (MAX) NOT NULL,
CONSTRAINT [PK_LoggedInUser] PRIMARY KEY CLUSTERED ([LoggedInUserID] ASC)
);
For this above query, say, if I have 7 chatoom topics in Basketball, I get Basketball's any 3 rooms shown & the whole Basketball is repeated 7 times (Not sorted properly to my expectation too) and similary, if I have 15 chatroom topics in Football, I get whole Football repeated 15 times without getting sorted properly too.
What are the mistakes, I have done here? Thanks in advance and have a nice day ahead.
Well with your method you are actually multiplying the row because of the two joins.
So you need to aggregate first, then join.
So in the end :
with agg_ChatUserLog as (
select RoomId, count(*) as cnt_user_tot
from ChatUserLog
group by RoomId),
agg_LoggedInUser as (
select RoomId, count(*) as cnt_user_logged
from LoggedInUser
group by RoomId)
select name, cnt_user_tot, cnt_user_logged
from Room r
left outer join agg_ChatUserLog acu on acu.RoomId = r.RoomId
left outer join agg_LoggedInUser alu on alu.RoomId = r.RoomId

Inner join - count and sum of field

I have two tables editors and title_editors that I am trying to run an inner join query to show all editors and how many books they edit. I am not getting the desired result but a total sum of all books edited. How can list the name of all editors and how many books they edit and arrange the report so the editor editing the most books is listed first? SQLFIDDLE
Query
SELECT (e.first_name || ' ' || e.last_name) as Editor_Name, SUM(te.editor_order) as Books_Edited FROM editors e
INNER JOIN title_editors te ON te.editor_id = e.editor_id ORDER BY SUM(te.editor_order);
Table Schema
create table editors (editor_id char(11) not null, editor_lname varchar(40) not null, editor_fname varchar(20) not null, editor_positon varchar(12) null, phone char(12) null, address varchar(40) null, city varchar(20) null, state char(2) null, zip char(5) null, ed_boss char(11) null );
create table title_editors (editor_id char(11) not null, title_id char(6) not null, editor_order tinyint null);
In addition to the comment about CONCAT, you are missing your GROUP BY, and a DESC at the end of your ORDER BY to get them sorted the way you want.
SELECT
CONCAT(e.editor_fname,' ',e.editor_lname),
SUM(te.editor_order)
FROM
editors e
INNER JOIN
title_editors te
ON te.editor_id = e.editor_id
GROUP BY
e.editor_fname,
e.editor_lname
ORDER BY
SUM(te.editor_order) DESC;
http://sqlfiddle.com/#!9/47bd4/28
http://sqlfiddle.com/#!9/47bd4/22
Just GROUP your results.
SELECT (CONCAT(e.editor_fname,' ',e.editor_lname)) as Editor_Name
, SUM(te.editor_order) as Books_Edited
FROM editors e
INNER JOIN title_editors te
ON te.editor_id = e.editor_id
GROUP BY e.editor_fname,e.editor_lname
ORDER BY Books_Edited;

Returning multiple aggregate functions as rows

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';