I will try to describe my problem here. Let's say that i have 3 tables:
1. sales
salesID (PK)
productID(FK) - FK that points to the sold product
storeID(FK) - FK that points to the store that sold the product
month - month in which the product was sold
year - year in which the product was sold
amount - amount(of money) for which the product was sold
2. product
productID (PK)
productName
3. store
storeID (PK)
storeName
I need the following query: For every store show the top selling product in that store for the specified year. So the result should look something like:
STORE PRODUCT AMOUNT
store1 product1 XXX amount
store2 product2 YYY amount
store3 product1 XYX amount
Where each amount would be the highest sum of all amounts in that year.
What I can do now is:
SELECT store.storeName
, product.ProductName
, SUM(sales.ammount)
FROM sales
JOIN product ON sales.productID = product.productID
JOIN store ON sales.storeID = store.storeID
GROUP BY store.storeName
, product.ProductName
WHERE sales.year = 'XXXX'
;
Where I get a sum per product and per store. After this I can use the cursor to go thru the entire table row by row and check which one has the highest amount for that store.
But I was wondering if it is possible to do that in a 'simple' query?
I'm using SQL Developer for Oracle 11g database.
And I would appreciate any help.
Not terribly familiar with Oracle, but perhaps something like:
WITH cte AS (SELECT store.storeName
, product.ProductName
, SUM(sales.ammount) as sales_amount
FROM sales
JOIN product ON sales.productID = product.productID
JOIN store ON sales.storeID = store.storeID
WHERE sales.year = 'XXXX'
GROUP BY store.storeName, product.ProductName
)
SELECT a.*
FROM cte a
JOIN (SELECT storeName
, MAX(sales_amount) as Max_Sales
FROM cte
GROUP BY storeName
)b
ON a.storeName = b.StoreName
AND a.sales_amount = b.Max_Sales;
If there's a tie that returns both entries, you can use ROW_NUMBER() instead to limit to one result per storeName .
Related
I am new to SQL and databases and I have created a basic db for a shop. Tables are: Purchase, Item, Product. I am trying to create a query that will pull back which grid had the most income. I have tried the code below:
SELECT PRODUCT.LATITUDE
, PRODUCT.LONGITUDE
, SUM(PRICE)"TOTAL"
, PRODUCT.PRODUCT_ID
, PURCHASE.PURCHASE_ID
, ITEM.PURCHASE_ID,
FROM PRODUCT
, PURCHASE
, ITEM,
WHERE PURCHASE.PURCHASE_ID = ITEM.PURCHASE_ID
AND ITEM.PRODUCT_ID = PRODUCT.PRODUCT_ID;
Any tips on how best to bring back these details?
Thanks!
Here you go:
SELECT PRODUCT.LATITUDE
, PRODUCT.LONGITUDE
, SUM(PRODUCT.PRICE) "TOTAL"
FROM PUCHARSE JOIN ITEM ON PUCHARSE.ID = ITEM.PUCHARSE_ID JOIN PRODUCT ON PRODUCT.ID = ITEM.PRODUCT_ID
GROUP BY
PRODUCT.LATITUDE,
PRODUCT.LONGITUDE
ORDER BY SUM(PRODUCT.PRICE) DESC
NULLS LAST;
Assuming that PRODUCT table contains information about geolocation in shop, price and from table Purchase you need only PRODUCT_ID(each sold out products is single row in this table - by this you have amount of sold out products in history).
I have tried following this and this(SQL Server specific solution) but were not helpful.
I have two tables, Product and Sale and I want to find how many products are sold on each day. But I want to pivot the table so that columns become the products name and each row will contain the amount of products sold for each day ordered by the day.
Simplified schema is as following
CREATE TABLE product (
id integer,
name varchar(40),
price float(2)
);
CREATE TABLE sale(
id integer,
product_id integer,
transaction_time timestamp
);
This is what I want
I only managed to aggregate the total sales per day per product but I am not able to pivot the product names.
select date(sale.transaction_date)
, product.id
, product.name
, count(product_id)
from sale inner join
product on sale.product_id = product.id
group by date(sale.transaction_date)
, product.id
, product.name
This is the situation so far
Please suggest.
You need pivoting logic, e.g.
select
s.transaction_date::date,
count(case when p.name = 'intelligent_rubber_clock' then 1 end) as intelligent_rubber_clock,
count(case when p.name = 'intelligent_iron_wallet' then 1 end) as intelligent_iron_wallet,
count(case when p.name = 'practical_marble_car' then 1 end) as practical_marble_car
from sale s
inner join product p
on s.product_id = p.id
group by
s.transaction_date::date;
Since your expected output aggregates by date alone, then only the transaction date should be in your GROUP BY clause. The trick used here is to take the count of a CASE expression which returns 1 when the record is from a given product, and 0 otherwise. This generates conditional counts for each product, all in separate columns. To add more columns, just add more conditional counts.
I have a problem by solving following task:
'Show for every seller how much he earned (quantity * product_price) by selling the product PS4 in the year 2013'
The relations are:
seller(id , seller_name, advertised_by);
product( id, product_name, product_price);
sale(id, seller_id, product_id, quantity, date);
I inserted following data:
INSERT into seller VALUES
(1,'Bob',NULL),
(2,'Mary',1),
(3,'Peter',1),
(4,'Parker',1),
(5,'Jeff',1);
INSERT INTO product VALUES
(1,'PS4',100),
(2,'XBOX One',300),
(3,'Laptop',500);
INSERT INTO sale VALUES
(1,1,1,1,'4 5 2013'),
(2,2,1,2,'5 6 2013'),
(3,3,1,3,'6 6 2013'),
(4,4,1,4,'6 6 2013');
I know not using foreign keys or using varchar for date isn't good but I want to have the example being simple.
SELECT seller.id,seller.seller_name, (sale.quantity * product.price) AS sale
FROM seller,product,sale
WHERE product.id = sale.product_id
AND product.product_name = 'PS4'
AND sale.date like '%2013'
GROUP by seller.id;
I know that I have to use a GROUP BY but grouping by seller.id doesn't work.
You need to group by every column that isn't aggregated, and apply an aggregate function to the others. Here, you need to add sellar_name to the group by clause (which shouldn't change the grouping, as the id is already unique), and sum the sales.
Also, as a side note, using implicit joins (having more than one table in the from clause) has been deprecated for several years, and it's recommended you use an explicit join instead:
SELECT seller.id,seller.seller_name, SUM(sale.quantity * product.price) AS sale
FROM seller
JOIN sale ON sale.seller_id = seller.id
JOIN product ON product.id = sale.product_id
WHERE product.product_name = 'PS4' AND sale.date like '%2013'
GROUP BY seller.id;
Sorry if the title seems confusing, it was the best I could come up with.
I can work with both excel(Dax since its a power query) and sql:
I have a situation where there are two product types being purchased, Type_A and Type_B.
I want to calculate a count of how many unique Loc_ID have purchased a "Type_A" Product type, AFTER purchasing a "Type_B" Product type.
From my example there are a total of 3 unique Loc_ID which would fall in this filter: Loc_01, Loc_02, and Loc_04
Any help is greatly appreciated
Try this (it works good if each loc_id purchased both type of products as in your example.
select count(*)
from
(select loc_id , max(date_purchased) dt
from table t where product_type = 'type_a'
group by loc_id) a,
(select loc_id , max(date_purchased) dt
from table t where product_type = 'type_b'
group by loc_id) b
where a.loc_id=b.loc_id and a.dt>b.dt;
This will work even if certain loc_id did not purchase both type of products
Try this:-
Select count(a.loc_id) as cnt_locations
from
your_table_name a
inner join
(
Select a.loc_id,b.date_purchased,b.Product_type
from
(
Select loc_id, min(date_purchased) as date_purchased
from
your_table_name
group by loc_id
) a
inner join
your_table_name b
on a.loc_id=b.loc_id and a.date_purchased =b.date_purchased
where Product_type ='Type_B'
) b
on
a.loc_id=b.loc_id
where a.date_purchased >b.date_purchased and a.Product_type ='Type_A'
I'm making and application in vb.net using Visual Studio 2005 and SQL Server 2000. I have to keep track of the stock. The stock when added has its status set as "Unsold". When some stock is removed then the transaction keeps the status of stock as "Sold". The status can also be "Expired" for the stock that has been expired and when expired stock is claimed to the company then the status is "claimed"...Now from all this I want to extract the stock which is currently in hand. At a basic level with two status values i.e. "Sold" and "Unsold" I'm using the following query to extract the results from database but it doesn't calculate the difference sold and unsold items...
select category, item_name,
sum(crtns_added) as Cartons, sum(pieces_added) as Pieces,
sum(total_price)
from Stock
where status = 'unsold'
group by category, item_name
I have also tried this
select category, item_name, (sum(crtns_added) - sum(crtns_removed)) as Cartons,
(sum(pieces_added)- sum(pieces_removed)) as Pieces,
sum(total_price)
from Stock
where status = 'unsold' or status = 'sold'
group by category, item_name
You need to use two sub-selects to select the items with the appropriate values - something like:
SELECT
category,
item_name,
(SELECT SUM(crtns_added) FROM dbo.Stock s1 WHERE s1.ItemID = s.ItemID AND s1.Status = 'unsold') 'Unsold Cartons',
(SELECT SUM(crtns_added) FROM dbo.Stock s2 WHERE s2.ItemID = s.ItemID AND s2.Status = 'sold') 'Sold Cartons'
FROM
dbo.Stock s
GROUP BY
category, item_name
This assume there's an itemId column that uniquely identifies your items - some kind of a primary key. With this technique, you can get the sum of the sold or unsold cartons or pieces - whatever you need.