How would you retrieve an entire column - sql

ID Name Price
--------------------------------------
1 item1 10
2 item2 40
3 item3 10
4 item4 20
5 item5 50
6 item6 20
Say you had this table above and wanted to retrieve the following:
ID Name Price
5 item5 50
But you wanted to retrieve the above by using the highest price. I am currently using the below code.
SELECT
MAX(price) AS Price,
Name,
ID
FROM
ExampleTable
GROUP BY
Name, ID;

In SQL Server we can try:
SELECT TOP 1 *
FROM yourTable
ORDER BY Price DESC;
If there could be more than one record tied for the highest price, and you also wanted to report all ties, then we could use WITH TIES:
SELECT TOP 1 WITH TIES *
FROM yourTable
ORDER BY Price DESC;
If you want to use TOP to select only certain columns, then just list those columns out, e.g.
SELECT TOP 1 ID, Price
to select only the ID and Price columns.

use top as your DBMS is sql server
select top 1 * from your_table
order by Price desc
You could also use window function
with t1 as
(
select * , row_number() over(order by Price desc) as rn from your_table
) select ID ,Name ,Price from t1 where rn=1

Related

SQL Split One Row To Multiple Rows Based on Column Number

I have an order table and I will keep it simple. I need to split the rows based on the quantity in the order. For example, if an order quantity is 4 I need to split the original rows into 4 rows with quantity of 1 each. Example data below.
ID FKID Product QTY
1 100 Widget 4
I need a result like this.
ID FKID Product QTY
1 100 Widget 1
2 100 Widget 1
3 100 Widget 1
4 100 Widget 1
Just another option using an ad-hoc tally table and a simple JOIN
Example
Select ID = row_number() over (partition by A.ID order by N)
,FKID
,Product
,Qty = 1
From YourTable A
Join (
Select Top (1000) N=Row_Number() Over (Order By (Select NULL))
From master..spt_values n1 ,master..spt_values n2
) B on N<=A.[QTY]
Returns
ID FKID Product Qty
1 100 Widget 1
2 100 Widget 1
3 100 Widget 1
4 100 Widget 1
One simple method is a recursive CTE:
with cte as (
select ID, FKID, Product, QTY
from t
union all
select ID, FKID, Product, QTY - 1
from t
where qty > 1
)
select id, fkid, product, 1 as qty
from cte;
The only caveat is that if qty can be 100 or greater, you'll need option (maxrecursion 0).

How do I find the Sum and Max value per Unique ID in HIVE?

basically how do I turn
id name quantity
1 Jerry 1
1 Jerry 2
1 Nana 1
2 Max 4
2 Lenny 3
into
id name quantity
1 Jerry 3
2 Max 4
in HIVE?
I want to sum up and find the highest quantity for each unique ID
You can use window functions with aggregation:
select id, name, quantity
from (select id, name, sum(quantity) as quantity,
row_number() over (partition by id order by sum(quantity) desc) as seqnum
from t
group by id, name
) t
where seqnum = 1;
You can first calculate the sum of quantity per group, then rank them according to descending quantity, and finally filter the rows with rank = 1.
select
id, name, quantity
from (
select
*,
row_number() over (partition by id order by quantity desc) as rn
from (
select id, name, sum(quantity) as quantity
from mytable
group by id, name
)
) where rn = 1;
try like below
with cte as
(
select id,name,sum(quantity) as q
from table_name group by id,name
) select id,name,q from cte t1
where t1.q=( select max(q) from cte t2 where t1.id=t2.id)

SQL sum grouped by field with all rows

I have this table:
id sale_id price
-------------------
1 1 100
2 1 200
3 2 50
4 3 50
I want this result:
id sale_id price sum(price by sale_id)
------------------------------------------
1 1 100 300
2 1 200 300
3 2 50 50
4 3 50 50
I tried this:
SELECT id, sale_id, price,
(SELECT sum(price) FROM sale_lines GROUP BY sale_id)
FROM sale_lines
But get the error that subquery returns different number of rows.
How can I do it?
I want all the rows of sale_lines table selecting all fields and adding the sum(price) grouped by sale_id.
You can use window function :
sum(price) over (partition by sale_id) as sum
If you want sub-query then you need to correlate them :
SELECT sl.id, sl.sale_id, sl.price,
(SELECT sum(sll.price)
FROM sale_lines sll
WHERE sl.sale_id = sll.sale_id
)
FROM sale_lines sl;
Don't use GROUP BY in the sub-query, make it a co-related sub-query:
SELECT sl1.id, sl1.sale_id, sl1.price,
(SELECT sum(sl2.price) FROM sale_lines sl2 where sl2.sale_id = sl.sale_id) as total
FROM sale_lines sl1
In addition to other approaches, You can use CROSS APPLY and get the sum.
SELECT id, sale_id,price, Price_Sum
FROM YourTable AS ot
CROSS APPLY
(SELECT SUM(price) AS Price_Sum
FROM YourTable
WHERE sale_id = ot.sale_id);
SELECT t1.*,
total_price
FROM `sale_lines` AS t1
JOIN(SELECT Sum(price) AS total_price,
sale_id
FROM sale_lines
GROUP BY sale_id) AS t2
ON t1.sale_id = t2.sale_id

SQL Max over multiple versions

I have a table with three columns
Product Version Price
1 1 25
1 2 15
1 3 25
2 1 8
2 2 8
2 3 4
3 1 25
3 2 10
3 3 5
I want to get the max price and the max version by product.
So in the above example the results would have product 1, version 3, price25. product 2, version 2, price 8.
Can you let me know how I would do this.
I'm on Teradata
If Teradata supports the ROW_NUMBER analytic function:
SELECT
Product,
Version,
Price
FROM (
SELECT
atable.*, /* or specify column names explicitly as necessary */
ROW_NUMBER() OVER (PARTITION BY Product
ORDER BY Price DESC, Version DESC) AS rn
FROM atable
) s
WHERE rn = 1
;
Using Teradata SQL this can be further simplified:
SELECT * FROM atable
QUALIFY
ROW_NUMBER()
OVER (PARTITION BY Product
ORDER BY Price DESC, Version DESC) = 1;
The QUALIFY is a Teradata extension to Standard SQL, it's similar to a HAVING for GROUP BY, it filters the result of a window function.
SELECT product
, max(version) as version
, max(price) as price
FROM mytable
GROUP BY product
Following code will select product, Highest value of version, Highest value of price and will sort at product using GROUP BY
SELECT [product], MAX([version]) as [MaxVersion], MAX([price]) as [MaxPrice]
FROM [NameOfTable]
GROUP BY [product]
More explanation on Max function:
Max function SQL
try this one
select p.Product, MAX(p.Price), (select MAX(Version) from Products where Product = p.Product and Price = MAX(p.price))
from Products as p
group by p.Product
it returns
(Product, price,version)
1 25 3 ,
2 8 2 ,
3 25 1

Second maximum and minimum values

Given a table with multiple rows of an int field and the same identifier, is it possible to return the 2nd maximum and 2nd minimum value from the table.
A table consists of
ID | number
------------------------
1 | 10
1 | 11
1 | 13
1 | 14
1 | 15
1 | 16
Final Result would be
ID | nMin | nMax
--------------------------------
1 | 11 | 15
You can use row_number to assign a ranking per ID. Then you can group by id and pick the rows with the ranking you're after. The following example picks the second lowest and third highest :
select id
, max(case when rnAsc = 2 then number end) as SecondLowest
, max(case when rnDesc = 3 then number end) as ThirdHighest
from (
select ID
, row_number() over (partition by ID order by number) as rnAsc
, row_number() over (partition by ID order by number desc) as rnDesc
) as SubQueryAlias
group by
id
The max is just to pick out the one non-null value; you can replace it with min or even avg and it would not affect the outcome.
This will work, but see caveats:
SELECT Id, number
INTO #T
FROM (
SELECT 1 ID, 10 number
UNION
SELECT 1 ID, 10 number
UNION
SELECT 1 ID, 11 number
UNION
SELECT 1 ID, 13 number
UNION
SELECT 1 ID, 14 number
UNION
SELECT 1 ID, 15 number
UNION
SELECT 1 ID, 16 number
) U;
WITH EX AS (
SELECT Id, MIN(number) MinNumber, MAX(number) MaxNumber
FROM #T
GROUP BY Id
)
SELECT #T.Id, MIN(number) nMin, MAX(number) nMax
FROM #T INNER JOIN
EX ON #T.Id = EX.Id
WHERE #T.number <> MinNumber AND #T.number <> MaxNumber
GROUP BY #T.Id
DROP TABLE #T;
If you have two MAX values that are the same value, this will not pick them up. So depending on how your data is presented you could be losing the proper result.
You could select the next minimum value by using the following method:
SELECT MAX(Number)
FROM
(
SELECT top 2 (Number)
FROM table1 t1
WHERE ID = {MyNumber}
order by Number
)a
It only works if you can restrict the inner query with a where clause
This would be a better way. I quickly put this together, but if you can combine the two queries, you will get exactly what you were looking for.
select *
from
(
select
myID,
myNumber,
row_number() over (order by myID) as myRowNumber
from MyTable
) x
where x.myRowNumber = 2
select *
from
(
select
myID,
myNumber,
row_number() over (order by myID desc) as myRowNumber
from MyTable
) y
where x.myRowNumber = 2
let the table name be tblName.
select max(number) from tblName where number not in (select max(number) from tblName);
same for min, just replace max with min.
As I myself learned just today the solution is to use LIMIT. You order the results so that the highest values are on top and limit the result to 2. Then you select that subselect and order it the other way round and only take the first one.
SELECT somefield FROM (
SELECT somefield from table
ORDER BY somefield DESC LIMIT 2)
ORDER BY somefield ASC LIMIT 1