I need to get all the customer name where their preference MINPRICE and MAXPRICE is the same.
Here's my schema:
CREATE TABLE CUSTOMER (
PHONE VARCHAR(25) NOT NULL,
NAME VARCHAR(25),
CONSTRAINT CUSTOMER_PKEY PRIMARY KEY (PHONE),
);
CREATE TABLE PREFERENCE (
PHONE VARCHAR(25) NOT NULL,
ITEM VARCHAR(25) NOT NULL,
MAXPRICE NUMBER(8,2),
MINPRICE NUMBER(8,2),
CONSTRAINT PREFERENCE_PKEY PRIMARY KEY (PHONE, ITEM),
CONSTRAINT PREFERENCE_FKEY FOREIGN KEY (PHONE) REFERENCES CUSTOMER (PHONE)
);
I think I need to do some compare between rows and rows? or create another views to compare? any easy way to do this?
its one to many. a customer can have multiple preferences so i need to query a list of customer that have the same minprice and maxprice. compare between rows minprice=minprice and maxprice=maxprice
A self-join on preference would find rows with the same price preference, but a different phone number:
select distinct c1.name
, p1.minprice
, p1.maxprice
from preference p1
join preference p2
on p1.phone <> p2.phone
and p1.minprice = p2.minprice
and p1.maxprice = p2.maxprice
join customer c1
on c1.phone = p1.phone
join customer c2
on c2.phone = p2.phone
order by
p1.minprice
, p1.maxprice
, c1.name
It seems strange that you have minprice and maxprice in your preference table. Is that a table that you update after each transaction, such that each customer only has 1 active preference record? I mean, it reads like a customer could pay two different prices for the same item, which seems odd.
Assuming customer and preference are 1:1
SELECT c.*
FROM customer c INNER JOIN preference p ON c.phone = p.phone
WHERE p.minprice = p.maxprice
However, if a customer can have multiple preferences and you are looking for minprice = maxprice for ALL item ... then you could do this
SELECT c.*
FROM (SELECT phone, MIN(minprice) as allMin, MAX(maxprice) as allMax
FROM preference
GROUP BY phone) p INNER JOIN customer c on p.phone = c.phone
WHERE allMin = allMax
This will show all the customer names that have the same price preferences.
SELECT minprice, maxprice, GROUP_CONCAT(name) names
FROM preference
JOIN customer USING (phone)
GROUP BY minprice, maxprice
HAVING COUNT(*) > 1
The HAVING clause prevents it showing preferences that have no duplicates. If you want to see those single-customer preferences, remove that line.
Related
I need to select the item name and the vendor name for each item that belongs to the vendor with a rating bigger than 4. And I can't find a way, I know it's something with joins but the 2 of them have the same column name.
CREATE TABLE venedors(
id int PRIMARY KEY,
name varchar2(20),
rating int)
CREATE TABLE items(
id int PRIMARY KEY,
name varchar2(20),
venedorId int references venedors(id))
If i understanded your problem.
Select items.name as itemName, venedors.name as vendorName
from items
inner join venedors
on items.venedorId = venedors.id
where venedors.rating > 4
If you want get all the vendors irrespective whether there are items associated with vendors or not, then try with left join as shown below:
Select v.name as vendorName, i.name as itemName
from venedors v
left join items i
on i.venedorId = v.id
where v.rating > 4
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%';
I have three tables: customer, order and line items. They are set up as follows:
CREATE TABLE cust_account(
cust_id DECIMAL(10) NOT NULL,
first VARCHAR(30),
last VARCHAR(30),
address VARCHAR(50),
PRIMARY KEY (cust_id));
CREATE TABLE orders(
order_num DECIMAL(10) NOT NULL,
cust_id DECIMAL(10) NOT NULL,
order_date DATE,
PRIMARY KEY (order_num));
CREATE TABLE lines(
order_num DECIMAL(10) NOT NULL,
line_id DECIMAL(10) NOT NULL,
item_num DECIMAL(10) NOT NULL,
price DECIMAL(10),
PRIMARY KEY (order_id, line_id),
FOREIGN KEY (item_id) REFERENCES products);
Using Oracle, I need to write a query that presents the average item price for for those customers that made more than 5 or more purchases. This is what I've been working with:
SELECT DISTINCT cust_account.cust_id,cust_account.first, cust_account.last, lines.AVG(price) AS average_price
FROM cust_account
JOIN orders
ON cust_account.cust_id = orders.cust_id
JOIN lines
ON lines.order_num = orders.order_num
WHERE lines.item_num IN (SELECT lines.item_num
FROM lines
JOIN orders
ON lines.order_num = orders.order_num
GROUP BY lines.order_num
HAVING COUNT(DISTINCT orders.cust_id) >= 5
);
... INNER JOIN all your tables together
... GROUP BY customer and compute the average price of each customer's lines
... use a HAVING clause to limit the results to groups having 5 or more purchases
Query:
SELECT ca.first, ca.last, avg(l.price) avg_price
FROM cust_account ca
INNER JOIN orders o ON o.cust_id = ca.cust_id
INNER JOIN lines l ON l.order_num = o.order_number
GROUP BY ca.first, ca.last
HAVING COUNT(distinct l.line_id) >=5
-- OR, maybe your requirement is ...
-- HAVING COUNT(distinct o.order_num) >= 5
-- ... the question was a bit unclear on this point
I think this is it. I don't think it will work right away (I know nothing about oracle) but I think you will get the idea:
SELECT orders.cust_id,
AVG(lines.price) AS average_price
FROM lines
JOIN orders ON orders.order_num = orders.order_num
WHERE orders.cust_id IN (SELECT orders.cust_id
FROM orders
GROUP BY orders.cust_id
HAVING COUNT(*) >= 5)
GROUP BY orders.cust_id;
Subquery selects customers that have more than 5 orders.
And main query just gets all lines from all orders made by this customers.
I guess you can eliminate subquery by using HAVING DISTINCT .... Anyways, one with subquery should work just fine.
UPD.
something like this
SELECT orders.cust_id,
AVG(lines.price) AS average_price
JOIN orders ON orders.order_num = orders.order_num
GROUP BY orders.cust_id
HAVING COUNT(DISTINCT orders.id) >= 5;
So I have two tables and I'm trying to display some data from both and remove the duplicates. Sorry, I'm new to SQL and databases. Here's my code
Table 1
CREATE TABLE customer
(
customer_id VARCHAR2(5),
customer_name VARCHAR2(50) NOT NULL,
customer_address VARCHAR2(150) NOT NULL,
customer_phone VARCHAR2(11) NOT NULL,
PRIMARY KEY (customer_id)
);
Table 2
CREATE TABLE shop
(
shop_id VARCHAR2(7),
shop_address VARCHAR2(150) NOT NULL,
customer_id VARCHAR2(7),
PRIMARY KEY (shop_id),
FOREIGN KEY (customer_id) REFERENCES customer (customer_id)
);
I want to display everything from the SHOP table, and customer_id, customer_name from the CUSTOMER TABLE.
I've tried this so far, but it's displaying everything from both tables and I get two duplicate customer_id columns:
SELECT *
FROM shop
JOIN customer ON shop.customer_id = customer.customer_id
ORDER BY customer_name;
Anyone able to help?
Thanks
Due to both tables has column customer_id, so you can show everything on shop table and only column customer_name from customer table
SELECT s.*, c.customer_name
FROM shop s
JOIN customer c ON s.customer_id = c.customer_id
ORDER BY c.customer_name;
select distinct c.customer_id, c.customer_name, s.*
from customer c
inner join shop s on c.customer_id = s.customer_id
To remove duplicates, you need to use distinct keyword
https://www.w3schools.com/sql/sql_distinct.asp
You need to manually list the columns you want. Using * will pull in every column from every table. SQL does not have any way of saying "select all columns except these...".
I hope you're only using * casually - it's a very bad idea to use SELECT * inside program code that then expects certain columns to exist in a particular order or with a certain name.
To save typing, you could use * for one of the tables and manually name the rest:
SELECT
customer.*,
shop.shop_id,
shop.shop_address
FROM
...
I have this database schema:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name char(50) NOT NULL UNIQUE
);
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name char(50) NOT NULL,
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
uid INTEGER REFERENCES users (id) NOT NULL,
pid INTEGER REFERENCES products (id) NOT NULL,
quantity INTEGER NOT NULL,
price FLOAT NOT NULL CHECK (price >= 0)
);
I am trying to write a query that will give me all combinations of users and products, as well as the total amount spent by the user on that product. Specifically, if I have 5 products and 5 users, there should be 25 rows in the table. Right now I have a query that almost gets the job done, however, if the user has never purchased that product then there is no row printed at all.
Here's what I've written so far:
SELECT u.name as username, p.name as productname, SUM(o.quantity * o.price) as totalPrice
FROM users u, orders o, products p
WHERE u.id = o.uid
AND p.id = o.pid
GROUP BY u.name, p.name
ORDER BY u.name, p.name
I figure that this requires some sort of join, but my SQL knowledge is limited and I am not sure what would be the best way to go about doing this. I think if somebody can help me figure this out then I will have a much better understanding.
You can do this using cross join and left join:
select u.name as username, p.name as productname,
sum(o.quantity * o.price) as totalPrice
from users u cross join
products p left join
orders o
on o.uid = u.id and o.pid = p.id
group by u.name, p.name;
The cross join generates all the rows. The left join brings in the matching rows. A simple rule when using SQL is: Never use commas in the FROM clause. Always use explicit JOIN syntax.