Update row only where max date - sql

I have the following data
Date Week ID Tot_Seconds O_Seconds Week_ID
8/14/2011 12:00:00 AM 5823 22180 170043 26043 18
8/21/2011 12:00:00 AM 5824 22180 126471 0 18
I am trying to update a column in another table the value of O_Seconds,where the week and ID match, but i would only like to update where max(date) for each Week. The reason, is the table with the data source has dates by week, where the the table I will update is daily, and using the query I currently have, it updates for example 26043 for all days where id and week match, skewing my future queries where I will sum the values of those columns.
Is there any way to just update the max date?

Something like this
The derived table is used to get the 1st row per week/ID
UPDATE
O
SET
SomeCol = S.O_Second
FROM
OtherTable O
JOIN
(
SELECT
Week, ID, O_Second,
ROW_NUMBER() OVER (PARTITION BY Week, ID ORDER BY Date DESC) AS rn
FROM
ThisTable
) S ON O.Week = S.Week AND O.ID = S.ID
WHERE
S.rn = 1
For SQL Server 2000 and earlier you need an aggregate. See DBA.SE for more

Related

Updating a table column with the 2nd oldest date in a row?

I would like to update the contents of the Date 1 column to reflect 2nd oldest date each row. The table has thousands of rows and ~15 columns, only a handful of which are dates. I've used the least funtion in the past to update this column with the oldest date in each row, but I can't figure out how to update it with the 2nd oldest date(1/15/2020 for row 1 and 04/15/2020 for row 2 in this instance). Any help would be greatly appreciated.
ID
Date 1
Date 2
Date 3
Date 4
001
01/14/2020
01/15/2020
01/16/2020
002
04/15/2020
03/20/2020
06/16/2020
The simplest option might be to unpivot:
select t.*, d.date
from mytable t
cross join lateral (
select date
from (values (t.date2), (t.date3), (t.date4)) d(date)
order by d.date
limit 1 offset 1
) d
If you wanted an update statement:
update mytable t
set date1 = (
select date
from (values (date2), (date3), (date4)) d(date)
order by d.date
limit 1 offset 1
)
Demo on DB Fiddle

Finding Max(Date) BEFORE specified date in Redshift SQL

I have a table (Table A) in SQL (AWS Redshift) where I've isolated my beginning population that contains account id's and dates. I'd like to take the output from that table and LEFT join back to the "accounts" table to ONLY return the start date that precedes or comes directly before the date stored in the table from my output.
Table A (Beg Pop)
-------
select account_id,
min(start_date),
min(end_date)
from accounts
group by 1;
I want to return ONLY the date that precedes the date in my current table where account_id match. I'm looking for something like...
Table B
-------
select a.account_id,
a.start_date,
a.end_date,
b.start_date_prev,
b.end_date_prev
from accounts as a
left join accounts as b on a.account_id = b.account_id
where max(b.start_date) less than a.start_date;
Ultimately, I want to return everything from table a and only the dates where max(start_date) is less than the start_date from table A. I know aggregation is not allowed in the WHERE clause and I guess I can do a subquery but I only want the Max date BEFORE the dates in my output. Any suggestions are greatly appreciated.
I want to return ONLY the date that precedes the date in my current table where account_id match
If you want the previous date for a given row, use lag():
select a.*,
lag(start_date) over (partition by account_id order by start_date) as prev_start_date
from accounts a;
As I understand from the requirement is to display all rows from a base table with the preceeding data sorted based on a column and with some conditions
Please check following example which I took from article Select Next and Previous Rows with Current Row using SQL CTE Expression
WITH CTE as (
SELECT
ROW_NUMBER() OVER (PARTITION BY account_id ORDER BY start_date) as RN,
*
FROM accounts
)
SELECT
PreviousRow.*,
CurrentRow.*,
NextRow.*
FROM CTE as CurrentRow
LEFT JOIN CTE as PreviousRow ON
PreviousRow.RN = CurrentRow.RN - 1 and PreviousRow.account_id = CurrentRow.account_id
LEFT JOIN CTE as NextRow ON
NextRow.RN = CurrentRow.RN + 1 and NextRow.account_id = CurrentRow.account_id
ORDER BY CurrentRow.account_id, CurrentRow.start_date;
I tested with following sample data and it seems to be working
create table accounts(account_id int, start_date date, end_date date);
insert into accounts values (1,'20201001','20201003');
insert into accounts values (1,'20201002','20201005');
insert into accounts values (1,'20201007','20201008');
insert into accounts values (1,'20201011','20201013');
insert into accounts values (2,'20201001','20201002');
insert into accounts values (2,'20201015','20201016');
Output is as follows

ORACLE SQL: Look for last row in column then update data from another data without affecting older data

i'm currently learning to code in Oracle SQL. Referring to example on photo i attached, I would like to my script to look for last date in Table A, if the date (Table A) is less than date in Table B, then insert only the latest date data from Table B to A without affecting older date data in Table A.
.
The reason is because Table B data is store by month, meaning that month Jan data will be purge out when going to Feb. So the purpose of Table A is to retain all the data i want from Table B.
And how do i embedded the script in table so that it autorun everyday?
Try this:
insert into TableA (
select * from TableB where date >(select max(date) from TableA)
);
If I understand correctly, in Oracle 12c+, you can use:
insert into a (date, sales)
select date, sales
from b
where b.date > (select max(a.date) from a)
order by date desc
fetch first 1 row only;
The order by and fetch ensure that only the most recent row is inserted.
In earlier versions, you can use a subquery:
insert into a (date, sales)
select date, sales
from (select b.*, row_number() over (order by date desc) as seqnum
from b
where b.date > (select max(a.date) from a)
) b
where seqnum = 1;
Note: If you run this code every day, you will just end up inserting every row of b into a. I assume you are aware of that.

PostrgreSQL count how many transactions in the last 7 days

Hi I'm a SQL noobie and have been working on this problem for hours on end.
I have a table of transactions and the field txnDate is of date data type. I've altered the table to add a column called txnLast7days which should count how many transactions exist in the table within the last 7 days of txnDate.
This is my table
What statement can I use to update all the table records at once and counts the # of transactions within a 7 day period based on txnDate and inserts the result in the txnLast7days column for each row?
This is the statement I'm currently using based on a suggestion, but I'm still not getting the right result.
UPDATE temp2
SET txnLast7Days = subquery.txnLast7Days
FROM
(
SELECT txnDate, sum(dateCounts.transactionCount) OVER (ORDER BY txnDate ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) as txnLast7Days
FROM (SELECT count(*) transactionCount, txnDate FROM temp2 GROUP BY txnDate) as dateCounts
) subquery
WHERE temp2.txnDate = subquery.txnDate
My current query is not updating the txnlast7days with the right count, as you can see here
my current query output
What you need to do is get a count for each txnDate and then get the rolling 7 day count for each txnDate.
The former is done with a simple COUNT(*) and GROUP BY on your table. The latter is done with a window function that looks back over the last 7 records, ordered by txnDate, and sums those counts up.
You can then use those results in an UPDATE query to populate your new column.
UPDATE yourtable
SET txnLast7Days = subquery.txnLast7Days
FROM
(
SELECT txnDate, sum(dateCounts.transactionCount) OVER (ORDER BY txnDate ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) as txnLast7Days
FROM (SELECT count(*) transactionCount, txnDate FROM yourtable GROUP BY txnDate) as dateCounts
) subquery
WHERE txnDate = subquery.txnDate

Return min date and corresponding amount to that distinct ID

Afternoon
I am trying to return the min value/ max values in SQL Server 2005 when I have multiple dates that are the same but the values in the Owed column are all different. I've already filtered the table down by my select statement into a temp table for a different query, when I've then tried to mirror I have all the duplicated dates that you can see below.
I now have a table that looks like:
ID| Date |Owes
-----------------
1 20110901 89
1 20110901 179
1 20110901 101
1 20110901 197
1 20110901 510
2 20111001 10
2 20111001 211
2 20111001 214
2 20111001 669
My current query:
Drop Table #Temp
Select Distinct Convert(Varchar(8), DateAdd(dd, Datediff(DD,0,DateDue),0),112)as Date
,ID
,Paid
Into #Temp
From Table
Where Paid <> '0'
Select ,Id
,Date
,Max(Owed)
,Min(Owed)
From #Temp
Group by ID, Date, Paid
Order By ID, Date, Paid
This doesn't strip out any of my dates that are the same, I'm new to SQL but I'm presuming its because my owed column has different values. I basically want to be able to pull back the first record as this will always be my minimum paid and my last record will always be my maximum owed to work out my total owed by ID.
I'm new to SQL so would like to understand what I've done wrong for my future knowledge of structuring queries?
Many Thanks
In your "select into"statement, you don't have an Owed column?
GROUP BY is the normal way you "strip out values that are the same". If you group by ID and Date, you will get one row in your result for each distinct pair of values in those two columns. Each row in the results represents ALL the rows in the underlying table, and aggregate functions like MIN, MAX, etc. can pull out values.
SELECT id, date, MAX(owes) as MaxOwes, MIN(owes) as minOwes
FROM myFavoriteTable
GROUP BY id, date
In SQL Server 2005 there are "windowing functions" that allow you to use aggregate functions on groups of records, without grouping. An example below. You will get one row for each row in the table:
SELECT id, date, owes,
MAX(Owes) over (PARTITION BY select, id) AS MaxOwes,
MIN(Owes) over (PARTITION BY select, id) AS MinOwes
FROM myfavoriteTable
If you name a column "MinOwes" it might sound like you're just fishing tho.
If you want to group by date you can't also group by ID, too, because ID is probably unique. Try:
Select ,Date
,Min(Owed) AS min_date
,Max(Owed) AS max_date
From #Temp
Group by Date
Order By Date
To get additional values from the row (your question is a bit vague there), you could utilize window functions:
SELECT DISTINCT
,Date
,first_value(ID) OVER (PARTITION BY Date ORDER BY Owed) AS min_owed_ID
,last_value(ID) OVER (PARTITION BY Date ORDER BY Owed) AS max_owed_ID
,first_value(Owed) OVER (PARTITION BY Date ORDER BY Owed) AS min_owed
,last_value(Owed) OVER (PARTITION BY Date ORDER BY Owed) AS max_owed
FROM #Temp
ORDER BY Date;