I am trying to select the min price of each condition category. I did some search and wrote the code below. However, it shows null for the selected fields. Any solution?
SELECT Sales.Sale_ID, Sales.Sale_Price, Sales.Condition
FROM Items
LEFT JOIN Sales ON ( Items.Item_ID = Sales.Item_ID
AND Sales.Expires_DateTime > NOW( )
AND Sales.Sale_Price = (
SELECT MIN( s2.Sale_Price )
FROM Sales s2
WHERE Sales.`Condition` = s2.`Condition` ) )
WHERE Items.ISBN =9780077225957
A little more complicated solution, but one that includes your Sale_ID is below.
SELECT TOP 1 Sale_Price, Sale_ID, Condition
FROM Sales
WHERE Sale_Price IN (SELECT MIN(Sale_Price)
FROM Sales
WHERE
Expires_DateTime > NOW()
AND
Item_ID IN
(SELECT Item_ID FROM Items WHERE ISBN = 9780077225957)
GROUP BY Condition )
The 'TOP 1' is there in case more than 1 sale had the same minimum price and you only wanted one returned.
(internal query taken directly from #Michael Ames answer)
If you don't need Sales.Sale_ID, this solution is simpler:
SELECT MIN(Sale_Price), Condition
FROM Sales
WHERE Expires_DateTime > NOW()
AND Item_ID IN
(SELECT Item_ID FROM Items WHERE ISBN = 9780077225957)
GROUP BY Condition
Good luck!
Related
I have a table with reviews for products. I want to sort product_ids that have more than 100 verified reviews(verified review is a review with verified_purshace=True) by the fraction of 5 star-reviews to all reviews. I tried to implement this in one select, but after numerous tries, I finish with the need to create views. I managed to write a query that counts a number of 5-star reviews, but can`t do better. Can anybody give me a hint?
My best query:
select *,count(*)
from (
select *
from reviews
where star_rating = 5
) low_reviews
left join (
select distinct filtered_reviews.product_id
from (
select *
from (
select verified_reviews.product_id, count(*) as verified_reviews_number
from (
select *
from reviews
where verified_purchase=True
) as verified_reviews
) as counted_verified_reviews
where counted_verified_reviews.verified_reviews_number > 100
) as filtered_reviews
) filtered_product_ids on low_reviews.product_id = filtered_product_ids.product_id;
Data example:
review_id customer_id product_id star_rating helpful_votes total_votes vine verified_purshase review_headline review_body review_date
14830128 R158AS05ZMH7VQ 0615349439 5 2 2 N false Planting a Church ... Witnessing To Dracula... 2011-02-14
I want to sort product_ids that have more than 100 verified reviews(verified review is a review with verified_purshace=True) by the fraction of 5 star-reviews to all reviews.
You don't provide sample data, but I would expect a query like this:
select product_id
from reviews
where verified_purchase
group by product_id
having count(*) > 100
order by avg( (review = 5)::int ) desc;
The expression avg( (review = 5)::int ) is a shorthand way of saying count(*) filter (where review = 5) * 1.0 / count(review). It works because it converts the expression review = 5 to an int, which is 1 for true and 0 for false. The average is the proportion of times when it is true.
Actually, the above assumes that you only care about review start ratings for verified purchases. If you want to include all reviews (even non-verified ones) for the ordering:
select product_id
from reviews
group by product_id
having count(*) filter (where verified_purchase) > 100
order by avg( (review = 5)::int ) desc;
SELECT Stock.*
FROM Stock
WHERE (
(
(Stock.ComputerPartNumber) In (SELECT [ComputerPartNumber] FROM [Stock] As Tmp GROUP BY [ComputerPartNumber] HAVING Count(*)=2)
)
AND
(
(Stock.EquipmentName)="EquipmentA" Or (Stock.EquipmentName)="EquipmentB")
)
OR (
(
(Stock.ComputerPartNumber) In (SELECT [ComputerPartNumber] FROM [Stock] As Tmp GROUP BY [ComputerPartNumber] HAVING Count(*)=1)
)
AND (
(Stock.EquipmentName)="EquipmentA" Or (Stock.EquipmentName)="EquipmentB"
)
);
I am using the above SQL to achieve below 3 items:-
Find out all of the ComputerPartNumber which used by EquipmentA and/or EquipmentB only
Filter out the query result if the ComputerPartNumber used by equipment other than EquipmentA and EquipmentB.
If the ComputerPartNumber is used by both EquipmentA and EquipmentC, filter out the result also.
However the item 3 cannot be filtered out successfully. What should I do in order to achieve the item3?
Table and Query snapshots are attached. Thanks in advance!
Table
Query
What you need to do is to check if the total number of times a part is used in all pieces of Equipment is equal to the total number of times a part is used by either Equipment A or B:
SELECT S.StorageID, S.ComputerPartNumber, S.EquipmentName, S.Result
FROM Stock AS S
WHERE
(SELECT COUNT(*) FROM Stock AS S1 WHERE S1.ComputerPartNumber=S.ComputerPartNumber)
=(SELECT COUNT(*) FROM Stock AS S2 WHERE S2.ComputerPartNumber=S.ComputerPartNumber AND S2.EquipmentName IN("EquipmentA","EquipmentB"))
Regards,
You can use not exists:
select s.*
from stock as s
where not exists (select 1
from stock as s2
where s2.ComputerPartNumber = s.ComputerPartNumber and
s2.EquipmentName not in ("EquipmentA", "EquipmentB")
);
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.
This is my table relation :
tbl_product
-----------
product_id
tbl_product_price
-----------------
price_id
price_product_id (FK)
price_normal
price_discount
price_disc_valid_from_date
price_disc_valid_to_date
I'd like to query tbl_product, ordered by its max price DESC, which must be validated first. If the the discount date is still valid (current date between price_disc_valid_from_date AND price_disc_valid_to_date), then get the price_discount. If not valid, then get price_normal. After that I need to get max price ( either from the price_discount or price_normal), then order by that max price.
Most of the questions like this are just how to select the max column, no validation needed first on the joined table.
My question is , what is the postgres sql statement for that query ? Thanks
[EDIT]
I stuck in selecting max price from table tbl_product_price but no idea how to join with tbl_product :
SELECT
pr.price_id, pr.product_price_id,
CASE WHEN current_date BETWEEN pr.price_disc_valid_from_date AND pr.price_disc_valid_to_date
THEN pr.price_discount
ELSE pr.price_normal END AS price
FROM tbl_product_price pr
WHERE pr.price_product_id = 316
GROUP BY pr.price_id, pr.price_product_id
ORDER BY price DESC
LIMIT 1;
Can you do something like this:
SELECT
tbl_tbl_product.price_product_id,
tblMax.MaxPrice
FROM
tbl_tbl_product
JOIN
(
SELECT
tbl_product_price.price_product_id,
MAX(
CASE
WHEN now() BETWEEN
tbl_product_price.price_disc_valid_from_date
AND tbl_product_price.price_disc_valid_to_date
THEN tbl_product_price.price_discount
ELSE tbl_product_price.price_normal
END
) AS MaxPrice
FROM
tbl_product_price
GROUP BY
tbl_product_price.price_product_id
) as tblMax
ON tblMax.price_product_id=tbl_tbl_product.product_id
ORDER BY
tblMax.MaxPrice DESC
If I understand your logic correctly, this query should return products ordered by the maximum price for the product:
SELECT
tp.product_id
FROM
tbl_product tp INNER JOIN tbl_product_price tpp
ON tb.product_id = tpp.price_product_id
GROUP BY
tp.product_id
ORDER BY
MAX(CASE WHEN current_date BETWEEN tpp.price_disc_valid_from_date
AND tpp.price_disc_valid_to_date THEN
tpp.price_discount
ELSE
tpp.price_normal END) DESC
I'm trying to find all duplicates in a Table and change one of their values.
Now i use:
SELECT Amount
FROM Bids
GROUP BY Amount, AuctionID
HAVING ( COUNT(Amount) > 1 ) AND (AuctionID=1)
The problem that it returns only
Amount
23.6500
41.8800
42.3500
And not
Amount
23.6500
23.6500
41.8800
41.8800
42.3500
42.3500
So I can't UPDATE all the rows.
How can I get it the way I showed?
Thanks,
Dan
Just wrap it inside an IN query:
SELECT Amount
FROM Bids
WHERE Amount IN (
SELECT Amount
FROM Bids
GROUP BY Amount, AuctionID
HAVING ( COUNT(Amount) > 1 ) AND (AuctionID=1)
)
UPDATE: added UPDATE statement
UPDATE Bids
SET Burned = 1
WHERE Amount IN (
SELECT Amount
FROM Bids
GROUP BY Amount, AuctionID
HAVING ( COUNT(Amount) > 1 ) AND (AuctionID=1)
)
Assume that you have Id in Bids table:
SELECT Amount
FROM Bids b1
WHERE AcutionId = 1
AND EXISTS (Select 1 from Bids b2
WHERE b2.AuctionID = b1.AuctionId
AND b1.Amount = b2.Amount
AND b1.Id <> b2.Id)
I'm curious to know why your original select doesn't satisfy your requirement. If for every member within a set of duplicates you're only selecting one of them, then you have one to update. It should be informative to add AuctionId to the select provided by Frank Schmitt to see what distinguishes these rows.