SQL Max over multiple versions - sql

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

Related

Find gaps of a sequence in PostgreSQL tables

I have a table invoices with a field invoice_number. This is what happens when i execute select invoice_number from invoice
invoice_number
1
2
3
5
6
10
11
I want a SQL that gives me the following result:
gap_start
gap_end
1
3
5
6
10
11
demo:db<>fiddle
You can use row_number() window function to create a row count and use the difference to your actual values as group criterion:
SELECT
MIN(invoice) AS start,
MAX(invoice) AS end
FROM (
SELECT
*,
invoice - row_number() OVER (ORDER BY invoice) as group_id
FROM t
) s
GROUP BY group_id
ORDER BY start

How would you retrieve an entire column

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

SQL query to find counts of numbers in running total

Suppose the table has 1 column ID and the values are as below:
ID
5
5
5
6
5
5
6
6
the output should be
ID count
5 3
6 1
5 2
6 2
How can we do that in a single SQL query.
If you want to find the Total count of the Records you have you can write like
select count(*) from database_name order by column_name;
In relational databases data in the table has no any order, see this: https://en.wikipedia.org/wiki/Table_(database)
the database system does not guarantee any ordering of the rows unless
an ORDER BY clause is specified in the SELECT statement that queries
the table.
therefore, in order to get desired results, you must have an additional colum in the table that defines an order of rows (and can by used in ORDER BY clause).
In the below examle cn column defines such an order:
select * from tab123 ORDER BY rn;
RN ID
---------- -------
1 5
2 5
3 5
4 6
5 5
6 5
7 6
8 6
Starting from Oracle version 12c new MATCH_REGOGNIZE clause can be used:
select * from tab123
match_recognize(
order by rn
measures
strt.id as id,
count(*) as cnt
one row per match
after match skip past last row
pattern( strt ss* )
define ss as ss.id = prev( ss.id )
);
On earlier versions that support windows function (Oracle 10 and above) you can use two windows functions: LAG ... over and SUM ... over, in this way
select max( id ) as id, count(*) as cnt
FROM (
select id, sum( xxx ) over (order by rn ) as yyy
from (
select t.*,
case lag( id ) over (order by rn )
when id then 0 else 1 end as xxx
from tab123 t
)
)
GROUP BY yyy
ORDER BY yyy;

split row_number() over partition over multiple columns

I have a query which uses row_number() over partition.
When the result comes out it looks like
Product Row_Number Price
A 1 25
A 2 20
A 3 15
B 1 100
B 2 10
B 3 2
I want to get the result to show over columns like
Product Row1 Row2 Row3 price1 price2 price3
A 1 2 3 25 20 15
B 1 2 3 100 10 2
Should I use something like rank()???
I'm using Teradata
You can add two more window functions to get the 2nd and 3rd highest price, this should run in the same STAT-step as your current ROW_NUMBER, so there's no additional overhead:
select
product,
price as Price1,
min(price)
over (partition by product
order by price desc
rows between 1 following and 1 following) as Price2,
min(price)
over (partition by product
order by price desc
rows between 2 following and 2 following) as Price3
from tab
qualify
row_number()
over (partition by product
order by price desc) = 1
I just give sort direction for each sort parameter , and then , it works , very fine. No Partition is used.
SELECT TOP (5) ROW_NUMBER() OVER (ORDER BY SCHEME ASC,APPLICATION_DATE DESC,TRANSACTION_REF_NO ASC,APPLICATION_STATUS DESC)

How can I use SUM() OVER()

I can't understand this code's bug
ID AccountID Quantity
1 1 10 Sum = 10
2 1 5 = 10 + 5 = 15
3 1 2 = 10 + 5 + 2 = 17
4 2 7 = 7
5 2 3 = 7 + 3 = 10
SELECT ID, AccountID, Quantity,
SUM(Quantity) OVER (PARTITION BY AccountID ) AS TopBorcT,
FROM tCariH
Seems like you expected the query to return running totals, but it must have given you the same values for both partitions of AccountID.
To obtain running totals with SUM() OVER (), you need to add an ORDER BY sub-clause after PARTITION BY …, like this:
SUM(Quantity) OVER (PARTITION BY AccountID ORDER BY ID)
But remember, not all database systems support ORDER BY in the OVER clause of a window aggregate function. (For instance, SQL Server didn't support it until the latest version, SQL Server 2012.)
if you are using SQL 2012 you should try
SELECT ID,
AccountID,
Quantity,
SUM(Quantity) OVER (PARTITION BY AccountID ORDER BY AccountID rows between unbounded preceding and current row ) AS TopBorcT,
FROM tCariH
if available, better order by date column.
Query would be like this:
SELECT ID, AccountID, Quantity,
SUM(Quantity) OVER (PARTITION BY AccountID ) AS TopBorcT
FROM #Empl ORDER BY AccountID
Partition by works like group by. Here we are grouping by AccountID so sum would be corresponding to AccountID.
First first case, AccountID = 1 , then sum(quantity) = 10 + 5 + 2 =>
17 & For AccountID = 2, then sum(Quantity) = 7+3 => 10
so result would appear like attached snapshot.