Query using Avg order by date - sql

I am querying a table with dates and numbers. I need top 10 dates in desc order and a value for the average column.
SELECT TOP (10) columnName1, AVG(columnNumber1) AS AvgNumber
WHERE ....
AND ...
GROUP BY columnName1
**Order by date desc**
to get the top resent dates i need to order by date desc
rgs
i need to sort the date column and then average the top ten. using group by i have to place date in select and get 10 results...i dont want to group by date. this probably not the way
eg
HireDate LocationID
2001-01-01 1
2002-08-12 1
1999-09-01 2
1996-03-16 1
2007-05-17 1
2001-11-15 4
2000-01-01 1
2001-11-15 NULL
2003-09-30 2
2004-10-04 2
1989-04-01 1
1995-05-26 4
select top (5) avg(locationid) from Employee
order by HireDate desc
Msg 8127, Level 16, State 1, Line 2
Column "Employee.HireDate" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.
Results required
HireDate LocationID
2007-05-17 1
2004-10-04 2
2003-09-30 2
2002-08-12 1
2001-11-15 4
Avg =2

To enforce the required logical order of operations, use a derived table: select top 10 rows based on the descending order of the date column, then use the result as a dataset to obtain the average from it:
SELECT AVG(Value)
FROM
(
SELECT TOP (10) Value
FROM YourTable
WHERE ...
ORDER BY DateColumn DESC
) AS s
;

The easiest way to achieve this is to add the date to the group by. If you don't want to return the date then you can wrap your result in another select to remove it, like this:
SELECT AVGLocation
FROM (SELECT TOP (5) avg(locationid) as AVGLocation, HireDate
FROM Employee
GROUP BY HireDate
ORDER BY HireDate desc) TableAliasName

Related

Get highest value from column in where clause

I have table:
id date day
2 21-07 1
2 10-07 3
2 11-07 2
I need to get date which has highest day, in current example it should be 10-07.
Next query works fine, but is there way to make it more optimised?
SELECT date
FROM (SELECT date, MAX(day)
FROM some_table
WHERE id = 2
GROUP BY date
LIMIT 1) x
I would not suggest a where clause. Just use:
select date
from some_table
where id = 2
order by day desc
limit 1;

select record from filtered results in postgreSQL

I have a function which gives me ordered rows (the function already order by the results):
By doing : select * from func1(ID)
Example A:
rownum date qty
1 1.1.10 -5
2 1.10.10 6
3 2.10.10 6
4 5.10.10 -2
5 6.10.10 -8
Example B:
rownum date qty
1 1.1.10 -7
2 1.10.10 6
Note: rownum is a column i calculate manually in my function. It's order is exact to my needs. So it's ok to be based on that.
I want to write a query which pass over the rows from bottom to top (highest rownum till lowest rownum) and return the date of the first encountered row that has negative qty
For example A the returned value is 6.10.10 (rownum 5 is the first row with negative value of qty)
for example B 1.1.10 (rownum 2 is the first row with negative value of qty)
How can I do that?
You could use ROW_NUMBER:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY rownum DESC) as rn
FROM func1(ID)
WHERE qty < 0
)
SELECT *
FROM cte
WHERE rn = 1;
I don't believe that table-valued functions in Postgres guarantee the ordering of the results. You will need to use an order by or some other mechanism.
If you want the most recent date with a negative value:
select max(date)
from func1(ID) t
where qty < 0;
If you have another ordering in mind:
select date
from func1(ID) t
where qty < 0
order by rownum desc -- your order by conditions here, but inverted
fetch first 1 row only;
This will allow you to fetch other values from the row, if you like.

displaying distinct column value with corresponding column random 3 values

I have a table employee with columns (state_cd,emp_id,emp_name,ai_cd) how can i display disticnt state_cd with 3 different values from ai_cd
the answer should be
state_cd ai_cd
------- --------
TX 1
2
5
CA 9
10
11
This type of operation is normally better done in the application. But, you can do it in the query, if you really want to:
select (case when row_number() over (partition by state_cd order by ai_cd) = 1
then state_cd
end) as state_cd,
ai_cd
from employee e
order by e.state_cd, e.ai_cd;
The order by is very important, because SQL result sets are unordered. Your result requires ordering in order to make sense.
Just group by state_id and then count using count(Distinct column_name_)
select state_id from (select state_id,COUNT(DISTINCT ai_cd) as cnt from employee group by state_id) where cnt==3

SQL query to select most recent of duplicates

I have a table of values, with a date stored against each entry for example
Name
Age
PaymentAmount
Date
Can someone help me to write a query that would show the most recent payment only of any person within a certain age range.
E.g If I had 5 entries, and wanted the most recent payment of all people aged 20-25
Allan, 45, $1500, 1/1/2014
Tim, 22, $1500, 1/2/2001
John, 25, $2000, 2/3/2001
Tim, 22, $2500, 1/2/2010
John, 25, $3000, 2/3/2010
It would return the bottom 2 rows only
You didn't state your DBMS, so this is ANSI SQL
select *
from (
select name,
age,
PaymentAmount,
Date,
row_number() over (partition by name order by date desc) as rn
from the_table
where age between 22 and 25
) t
where rn = 1;
Another option is to use a co-related subquery:
select name,age,paymentamount,date
from the_table t1
where age between 22 and 25
and date = (select max(date)
from the_table t2
where t2.name = t1.name
and t2.age between 22 and 25)
order by name;
Usually the solution with a window function is faster than the co-related subquery as only a single access to the table is needed.
SQLFiddle: http://sqlfiddle.com/#!15/17e37/4
Btw: having a column named age is a bit suspicious because you need to update that every year. You should rather store the date of birth and then calculate the age when retrieving the data.
This query would give you all records of most recent payment of age 20 and 25. Limit it by using TOP 2 or LIMIT 2 or rownum <=2 as per your DB syntax
SELECT NAME,AGE,PAYMENTAMOUNT,DATE FROM MY_TABLE
WHERE AGE BETWEEN 20 AND 25
AND DATE IN
(
SELECT MAX(DATE)
FROM MY_TABLE
WHERE
AGE BETWEEN 20 AND 25
);
EDIT as per horse_with_no_name:
SELECT NAME,AGE,PAYMENTAMOUNT,DATE
FROM the_table
WHERE AGE BETWEEN 20 AND 25
AND DATE IN
(
SELECT (DATE)
FROM the_table
WHERE
AGE BETWEEN 20 AND 25 order by date desc limit 2
)
limit 2;
Fiddle reference : http://sqlfiddle.com/#!15/17e37/10
Simplest of all,Try this following query
select name,age,paymentamount,date from yourtablename where date in (select max(date) from yourtablename where age between 20 and 25 and group by name);
You should Create a Table with Identity Column to make your Life easier
ColumnPrimaryKey IDENTITY (1,1)
Name
Age
PaymentAmount
Date
SELECT TOP 2 * FROM [TableName] Where Age BETWEEN 20 AND 25 ORDER BY [PrimaryKey] DESC
The above query will return the top two row Inserted in table
You can use between like
select * from meta where title='$title' and (date between '$start_date' and '$end_date').
Okay, I know you said SQL-- here's for people with two layers.
VIA SQL:
Order your SQL results by date descending (should be newest to oldest...).
VIA YOUR "BACK END":
Create an empty final set.
As you are iterating through your results, if your result row person is not in your final set, add the data to the final set.
Boom, your final set has the latest of each person.

Select particular not grouped column from grouped set

The topic might be a little bit unclear but I couldn't describe in a single sentence what I want to achieve.
Say I have a table that is (columns)
id INT PK
name VARCHAR
date DATE
I have a grouping select
select
name,
max(date)
from table
group by name
that gives me a name and the latest date.
What is the easiest way to join the id column to the current aggregated result set with the id value where the date was the maximum?
Let me explain what my goal is with an example:
The table is filled with the data as follows
id name date
1 david 2012-12-12
2 david 2013-12-02
3 patrick 2014-01-02
4 patrick 2012-11-11
and by my query I'd like to get the following result
id name date
2 david 2013-12-02
3 patrick 2014-01-02
Notice that all the records for name = 'david' are aggregated and the maximum date is selected. How to get the row id for this maximum date?
One option is to use ROW_NUMBER():
SELECT id, name, date
FROM (
SELECT id, name, date,
row_number() over (partition by name order by date desc) rn
FROM yourtable
) t
WHERE rn = 1
SQL Fiddle Demo
Another option is to join the table back to itself using the MAX() aggregate. This option could potentially result in ties if multiple id/name combinations share the same max date:
SELECT t.id, t.name, t.date
FROM yourtable t
JOIN (SELECT name, max(date) maxdate
FROM yourtable
GROUP BY name) t2 on t.name = t2.name AND t.date = t2.maxdate
More Fiddle