How to find most recent date given a set a values that fulfill condition * - sql

I've been trying to build an sql query that finds from (table) the most recent date for selected id's that fulfill the condition where 'type' is in hierarchy 'vegetables'. My goal is to be able to get the whole row once max(date) and hierarchy conditions are met for each id.
Example values
ID DATE PREFERENCE AGE
123 1/3/2013 carrot 14
123 1/3/2013 apple 12
123 1/2/2013 carrot 14
124 1/5/2013 carrot 13
124 1/3/2013 apple 13
124 1/2/2013 carrot 14
125 1/4/2013 carrot 13
125 1/3/2013 apple 14
125 1/2/2013 carrot 13
I tried the following
SELECT *
FROM table
WHERE date in
(SELECT max(date) FROM (table) WHERE id in (123,124,125))
and preference in
(SELECT preference FROM (hierarchy_table)
WHERE hierarchy = vegetables))
and id in (123,24,125)
but it doesn't give me the most recent date for each id that meets the hierarchy conditions. (ex. in this scenario I would only get id 124)
Thank you in advance!

SELECT max(date) FROM (table) WHERE id in (123,124,125)
is giving you the max date from all dates, you need to group them.
Try replacing with:
SELECT max(date) FROM (table) GROUP BY id
This way you will get the max date for each id

I figured this out. Please see the query below as an example:
SELECT * FROM (table) t
WHERE t.date in
(SELECT max(date) FROM table sub_t where t.ID = sub_t.ID and (date !> (currentdate))
and preference in
(SELECT preference FROM (hierarchy_table) WHERE hierarchy ='vegetables')
and ID in ('124')

Change:
max(date)
To:
-- if your date data is in mm/dd/yyyy
max( str_to_date( date, '%m/%d/%Y' ) )
OR
-- if your date data is in dd/mm/yyyy
max( str_to_date( date, '%d/%m/%Y' ) )

Related

Select the latest NEW rows by Date from the Snapshot Table

I have a snapshot table like the following
id
name
value
date
123
ABC Corp
500
yesterday
123
ABC Corp
500
today
456
XYZ Ltd.
700
today
123
ABC Corp
500
tomorrow
456
XYZ Ltd.
700
tomorrow
789
PQR Consulting
100
tomorrow
I would like to get the new rows only like the following table from the above snapshot table using sql
id
name
value
date
456
XYZ Ltd.
700
today
789
PQR Consulting
100
tomorrow
I need a pointer whether to follow the window function (like LAG() etc.) to get the new table. or more simple solution is there? Thanks in advance!
There are a few options here, one of them is to use a cte or a derived table to add row_number based on the date column to the table, and the other is to use first_value window function. I'm pretty sure the derived table solution would be better in terms of performance, but I don't have the time to test.
Here's what I would do:
;WITH cte AS
(
SELECT id, name, value, date, ROW_NUMBER() OVER(PARTITION BY id ORDER BY date DESC) as rn
FROM snapshotTable
)
SELECT id, name, value, date
FROM cte
WHERE rn = 1;
To get the earliest records all you need to do is remove the DESC from the order by clause.

How to calculate average monthly number of some action in some perdion in Teradata SQL?

I have table in Teradata SQL like below:
ID trans_date
------------------------
123 | 2021-01-01
887 | 2021-01-15
123 | 2021-02-10
45 | 2021-03-11
789 | 2021-10-01
45 | 2021-09-02
And I need to calculate average monthly number of transactions made by customers in a period between 2021-01-01 and 2021-09-01, so client with "ID" = 789 will not be calculated because he made transaction later.
In the first month (01) were 2 transactions
In the second month was 1 transaction
In the third month was 1 transaction
In the nineth month was 1 transactions
So the result should be (2+1+1+1) / 4 = 1.25, isn't is ?
How can I calculate it in Teradata SQL? Of course I showed you sample of my data.
SELECT ID, AVG(txns) FROM
(SELECT ID, TRUNC(trans_date,'MON') as mth, COUNT(*) as txns
FROM mytable
-- WHERE condition matches the question but likely want to
-- use end date 2021-09-30 or use mth instead of trans_date
WHERE trans_date BETWEEN date'2021-01-01' and date'2021-09-01'
GROUP BY id, mth) mth_txn
GROUP BY id;
Your logic translated to SQL:
--(2+1+1+1) / 4
SELECT id, COUNT(*) / COUNT(DISTINCT TRUNC(trans_date,'MON')) AS avg_tx
FROM mytable
WHERE trans_date BETWEEN date'2021-01-01' and date'2021-09-01'
GROUP BY id;
You should compare to Fred's answer to see which is more efficent on your data.

Find Column With Max on Other Column Grouping By Another Column

I have a table like this:
Id - ItemId - Price - SalesId - Date
1 12 99.99924 21899234 2025-01-01 00:00:00.000000
2 123 12.34567 348923 2021-01-01 00:00:00.000000
3 1234 1234.5 3321234 2022-01-01 00:00:00.000000
4 12345 3.3246 2154234 2023-01-01 00:00:00.000000
5 1234 451.234 3423 2020-02-01 00:00:00.000000
6 12345 0.989 71112357 2020-09-15 20:20.10.000000
7 123 3435.3 71112357 2020-09-14 20:10:12.000000
I am trying to find the Price of an Item with latest Date. For example, if we tried to find ItemId = 1234, the one with the latest date is this 2022-01-01 00:00:00.000000 that has Id = 3, it has the price of 1234.5. That's what I'm trying to find by this query, the price of this item.
I am a beginner to SQL and tried the following query, but it gives me this error:
select "ItemId",
max("Date"),
"Price"
from "Products"
group by "ItemId"
[42803] ERROR: column "Products.Price" must appear in the GROUP BY clause or be used in an aggregate function
I appreciate any help here. Thank you!
In Postgres, you can use distinct on:
select distinct on ("ItemId") p.*
from "Products" p
order by "ItemId", "Date" desc;
Note: If you are learning SQL, don't use double quotes for string and column names.
You can try using row_number()
select * from
(
select ItemId,Date,Price,row_number() over(partition by itemid order by date desc) as rn
from Products
)A where rn=1

max data in one column based on another column in sql

Hello I am very new to SQL programming, started last week. I am trying to select a userID and Maxdate from a table that looks like this for example:
Key USERID Date
1 111 12/1/2014
2 202 4/1/2014
3 111 3/8/2014
4 111 2/5/2014
5 202 2/10/2014
I want to make a query that would end up with the following results:
USERID DATE
111 12/1/2014
202 4/1/2014
Simply use GROUP BY clause with aggregate function MAX to achieve this:
Try this:
SELECT USERID, MAX(Date) AS Date
FROM tableA
GROUP BY USERID

Select info from table where row has max date

My table looks something like this:
group date cash checks
1 1/1/2013 0 0
2 1/1/2013 0 800
1 1/3/2013 0 700
3 1/1/2013 0 600
1 1/2/2013 0 400
3 1/5/2013 0 200
-- Do not need cash just demonstrating that table has more information in it
I want to get the each unique group where date is max and checks is greater than 0. So the return would look something like:
group date checks
2 1/1/2013 800
1 1/3/2013 700
3 1/5/2013 200
attempted code:
SELECT group,MAX(date),checks
FROM table
WHERE checks>0
GROUP BY group
ORDER BY group DESC
problem with that though is it gives me all the dates and checks rather than just the max date row.
using ms sql server 2005
SELECT group,MAX(date) as max_date
FROM table
WHERE checks>0
GROUP BY group
That works to get the max date..join it back to your data to get the other columns:
Select group,max_date,checks
from table t
inner join
(SELECT group,MAX(date) as max_date
FROM table
WHERE checks>0
GROUP BY group)a
on a.group = t.group and a.max_date = date
Inner join functions as the filter to get the max record only.
FYI, your column names are horrid, don't use reserved words for columns (group, date, table).
You can use a window MAX() like this:
SELECT
*,
max_date = MAX(date) OVER (PARTITION BY group)
FROM table
to get max dates per group alongside other data:
group date cash checks max_date
----- -------- ---- ------ --------
1 1/1/2013 0 0 1/3/2013
2 1/1/2013 0 800 1/1/2013
1 1/3/2013 0 700 1/3/2013
3 1/1/2013 0 600 1/5/2013
1 1/2/2013 0 400 1/3/2013
3 1/5/2013 0 200 1/5/2013
Using the above output as a derived table, you can then get only rows where date matches max_date:
SELECT
group,
date,
checks
FROM (
SELECT
*,
max_date = MAX(date) OVER (PARTITION BY group)
FROM table
) AS s
WHERE date = max_date
;
to get the desired result.
Basically, this is similar to #Twelfth's suggestion but avoids a join and may thus be more efficient.
You can try the method at SQL Fiddle.
Using an in can have a performance impact. Joining two subqueries will not have the same performance impact and can be accomplished like this:
SELECT *
FROM (SELECT msisdn
,callid
,Change_color
,play_file_name
,date_played
FROM insert_log
WHERE play_file_name NOT IN('Prompt1','Conclusion_Prompt_1','silent')
ORDER BY callid ASC) t1
JOIN (SELECT MAX(date_played) AS date_played
FROM insert_log GROUP BY callid) t2
ON t1.date_played = t2.date_played
SELECT distinct
group,
max_date = MAX(date) OVER (PARTITION BY group), checks
FROM table
Should work.