Get related fields from MAX() query - sql

I am trying to write a subquery that will select the highest price as well as the item name associated with that highest price.
For example:
ID | Price | Item Name
1 | 28.99 | Lamp
2 | 13.99 | USB Cable
I am expecting to get "28.99" and "Lamp" with my sub-query. The main query looks something like this:
SELECT
i.id
FROM
inventory i
My sub-query within the main query looks something like this:
SELECT
i.id,
(SELECT MAX(pl.price) FROM price_list pl WHERE pl.id = i.id) AS highest,
(SELECT MAX(pl.item_name) FROM price_list pl WHERE pl.id = i.id) AS highestName
FROM
inventory i
However, using MAX() on an item name is going to return the highest ranked alphabetical name, which is not what I want. I want to get the item name associated with the highest price. What is the most efficient way to do this?

You coudl use a subquery for match the where
select price as highest , item_name highestName
from price
where price = (
select max(Price)
from price_list
)

It can be done with a query like this:
SELECT Price, Name
FROM price_list
WHERE Price = (SELECT MAX(PL.Price) FROM price_list PL)

Related

SQL select all rows have the same value

I would like to show all rows that have the same product no from the product table. I try this code but I got the error
00000 - "column ambiguously defined"
WITH cte AS(
SELECT product_no
FROM product
GROUP BY product_no
HAVING COUNT(*) > 1)
select * from product v
inner join cte on cte.product_no = v.product_no
where
ACCOUNTING_GROUP not in ('1000','1200')
The result I would like to have:
Product_no produc_Descrip ACCOUNTING_GROUP acc_group_descr
123 bike 1001 semi-finish-A
123 bike 1002 semi-finish-B
1234 motor 1005 ........
1234 motor 1006 ........
.... ....... .... ........
I'm not sure about my answer because some information are missing, we don't know the structure of table product but what I can see is that you are joining on "cte.PART_NO" and this field is not defined or selected in your with clause "SELECT product_no".
You might try something like
SELECT PART_NO, COUNT(1) FROM product
GROUP BY PART_NO
HAVING COUNT(1) > 1)
But in order to provide a better answer we need the structure of your table with some examples of data inserted and result expected. At the moment you select "*" and expect 2 columns as result which also seem ambiguous.
Currently, your query select all product that aren't in group 1000 or 1200 and that appears 2 times or more in the table product, is that what you are really looking for ?
Assuming you have a unique column such as accounting_group, I would just use exists:
select p.*
from products p
where exists (select 1
from products p2
where p2.product_no = p.product_no and
p2.accounting_group <> p.accounting_group
)
order by p.product_no;
If this is not the case, go for window functions:
select p.*
from (select p.*, count(*) over (partition by product_no) as cnt
from product p
) p
where cnt >= 2
order by product_no;
for what you're trying to accomplish I'd probably change the query a bit,
with CTE as (SELECT PRODUCT_NO
FROM PRODUCT
GROUP BY PRODUCT_NO
HAVING COUNT(*) >1)
SELECT PRODUCT_NO, produc_descrip, ACCOUNTING_GROUP, acc_group_descr
FROM PRODUCT V
WHERE PRODUCT_NO IN(SELECT PRODUCT_NO FROM CTE)
AND ACCOUNT_GROUP NOT IN('1000','1200');
Though honestly, I don't think you need to use a with statement here, you could have simply used a nested query to accomplish the same thing.
Here is an optimized version, you can try.
SELECT * FROM PRODUCTS P
JOIN (SELECT PRODUCT_NO FROM PRODUCTS WHERE ACCOUNTING_GROUP NOT IN ('1000','1200') GROUP BY PRODUCT_NO HAVING COUNT(*) > 1 )TEMP
ON P.PRODUCT_NO = TEMP.PRODUCT_NO

SQL - Only one result per set

I have a SQL problem (MS SQL Server 2012), where I only want one result per set, but have different items in some rows, so a group by doesn't work.
Here is the statement:
Select Deliverer, ItemNumber, min(Price)
From MyTable
Group By Deliverer, ItemNumber
So I want the deliverer with the lowest price for one item.
With this query I get the lowest price for each deliverer.
So a result like:
DelA 12345 1,25
DelB 11111 2,31
And not like
DelA 12345 1,25
DelB 12345 1,35
DelB 11111 2,31
DelC 11111 2,35
I know it is probably a stupid question with an easy solution, but I tried for about three hours now and just can't find a solution. Needles to say, I'm not very experienced with SQL.
Just Add an aggregate function to your deliverer field also, as appropriate (Either min or max). From your data, I guess you need min(deliverer) and hence use the below query to get your desired result.
Select mIN(Deliverer), ItemNumber, min(Price)
From MyTable
Group By ItemNumber;
EDIT:
Below query should help you get the deliverer with the lowest price item-wise:
SELECT TABA.ITEMNUMBER, TABA.MINPRICE, TABB.DELIVERER
FROM
(
SELECT ITEMNUMBER, MIN(PRICE) MINPRICE
FROM MYTABLE GROUP BY
ITEMNUMBER
) TABA JOIN
MYTABLE TABB
ON TABA.ITEMNUMBER=TABB.ITEMNUMBER AND
TABA.MINPRICE = TABB.PRICE
You should be able to do this with the RANK() (or DENSE_RANK()) functions, and a bit of partitioning, so something like:
; With rankings as (
SELECT Deliverer,
rankings.ItemNumber,
rankings.Price
RANK() OVER (PARTITION BY ItemNumber ORDER BY Price ASC) AS Ranking
FROM MyTable (Deliverer, ItemNumber, Price)
)
SELECT rankings.Deliverer,
rankings.ItemNumber,
rankings.Price
FROM rankings
WHERE ranking = 1

Multiple WHERE OR Expression in query using SQL Server

I have here the Query to Select Multiple Expression
SELECT * FROM tbProducts WHERE
(PRICE BETWEEN 4590 AND 5100) AND RATING = (SELECT MAX(RATING) FROM tbxProducts) AND
(PRICE = (SELECT MAX(PRICE) FROM tbxProducts))
These are the columns from tbProdcts
| PRODUCT_NAME | DESCRIPTION | RATING | PRICE |
but the problem is that the table cannot display any Items with the range of 4590 up to 5100
And after that. I would select also the max rate of an items and max Price with that Range of Price
how can I do it with the right query?
Thanks in Advanced :)
This should do what you're asking for in a somewhat more straight forward manner.
It will return the item with the highest rating. If there are multiple items with the same highest rating, it will use the highest price as a tie breaker.
SELECT TOP 1 *
FROM tbProducts
WHERE price BETWEEN 4590 AND 5100
ORDER BY rating DESC, price DESC
you need to limit the output of
SELECT MAX(PRICE) FROM tbxProducts
so something like
SELECT MAX(PRICE) FROM tbxProducts t where t.PRICE BETWEEN 4590 AND 5100

Finding the total amount for my query

I have a query that allows me to retrieve customer orders.
Select ID, OrderID, Item, Price from customerOrders
Where Order = 1
is there a way of totalling up the final amount to pay and have it visible below, but still be able to view all details needed in the sql query, for example
ID | OrderID | Item | Price
1 | 1 | Book | 9.99
2 | 1 | DVD | 12.99
total = 22.98
Many thanks in advance
Two steps:
1, To generate the SUM, you need to add it to the result set using UNION ALL. UNION adds a DISTINCT operation which isn't required, even if in your case it won't change the result.
Select ID, OrderID, Item, Price from customerOrders
Where [Order] = 1
UNION ALL
Select NULL, NULL, NULL, SUM(Price) from customerOrders
Where [Order] = 1
ORDER BY CASE WHEN ID IS NULL THEN 2 ELSE 1 END, ID;
2, To sort it in the order you want (sum at the bottom), you can use the NULL ID as an identifier.
You can try COMPUTE
Select ID, OrderID, Item, Price from customerOrders
Where Order = 1
COMPUTE SUM(Price)
Technically, the thing you want is called a roll-up row. SQL Server has a special function for such cases, it's called ROLLUP() and used inside a GROUP BY clause. In your particular situation, the query would basically look like this:
SELECT ID, OrderID, Item, SUM(Price) AS Price
FROM customerOrders
WHERE OrderID = 1
GROUP BY ROLLUP((ID, OrderID, Item))
;
You can see a live demonstration of this query at SQL Fiddle. More information about ROLLUP(), as well as other GROUP BY functions, can be found at MSDN.
This is what you need:
Select ID, OrderID, Item, Price from customerOrders
Where Order = 1
Union
Select NULL, NULL, NULL, (
Select Sum(Price) from customerOrders
Where Order = 1
Group By Order
)
UPDATE
Incase the result was empty, the total should be zero, not empty. Use the updated code.
Cheers

Find the highest number of occurences in a column in SQL

Given this table:
Order
custName description to_char(price)
A desa $14
B desb $14
C desc $21
D desd $65
E dese $21
F desf $78
G desg $14
H desh $21
I am trying to display the whole row where prices have the highest occurances, in this case $14 and $21
I believe there needs to be a subquery. So i started out with this:
select max(count(price))
from orders
group by price
which gives me 3.
after some time i didn't think that was helpful. i believe i needed the value 14 and 21 rather the the count so i can put that in the where clause. but I'm stuck how to display that. any help?
UPDATE: So I got it to query the 14 and 21 from this
select price
from orders
group by price
having (count(price)) in
(select max(count(price))
from orders
group by price)
but i need it to display the custname and description column which i get an error:
select custname, description, price
from orders
group by price
having (count(price)) in
(select max(count(price))
from orders
group by price)
SQL Error: ORA-00979: not a GROUP BY expression
any help on this?
I guess you are pretty close. Since HAVING operates on the GROUPed result set, try
HAVING COUNT(price) IN
or
HAVING COUNT(price) =
replacing your current line.
Since you tagged the question as oracle, you can use windowing functions to get aggregate and detail data within the same query.
SELECT COUNT (price) OVER (PARTITION BY price) count_at_this_price,
o.*
from orders o
order by 1 desc
select employee, count(employee)
from work
group by employee
having count(employee) =
( select max(cnt) from
( select employee, count(employee cnt
from work
group by employee
)
);
Reference
You could try something like
select * from orders where price in (select top 2 price from orders group by price order by price desc)
I'm not sure of limiting results in Oracle, in SQL Server is top, maybe you should use limit.