SQL Query to update earliest date for unique combinations - sql

I am trying to update the Contract_Start date to be the earliest date for each unique Company and Route combination. For example, the Contract_Start for the first three records should be 1/15/12 as Company = 1 and Route = 1 for all three. The Contract_Start would then change to 1/20/12 for record 4 as that is the earliest date for the combination of Company = 1 and Route = 2. Any help would be greatly appreciated.
Company Route Driver Date Contract_Start
1 1 A 1/29/12
1 1 B 2/3/12
1 1 C 1/15/12
1 2 A 1/28/12
1 2 B 1/20/12
2 1 A 1/7/12
2 1 B 1/16/12
2 2 A 2/9/12
1 2 B 1/4/12

Update query with subquery can solve your problem
UPDATE TABLE TABLE T
SET CONTRACT_START = (
SELECT MIN(DATE)
FROM TABLE TI
WHERE T.COMPANY = TI.COMPANY
AND T.ROUTE = TI.ROUTE
)

Use window function to get Contract_Start. You needn't to store it at the table.
select Company, Route, Driver, Date, min(Date) over(partition by Company, Route) as Contract_Start
from myTable;

Use an updatable CTE with window functions:
with toupdate as (
select t.*, min(date) over (partition by company, route) as min_date
from t
)
update toupdate
set contract_start = min_date;
Updatable CTE/subqueries/views are a very handy feature in SQL Server and quite powerful when combined with window functions.

I hope this approach will resolve your issue and fulfill your task requirements.
UPDATE TABLE SET Contract_Start = CE.Date1
FROM Table_Name TB JOIN (
SELECT Company,Route,date1, Count(*) AS Countnum,
Row_Number() OVER(PARTITION BY Company, Route ORDER BY date1 ASC) AS Rownumber
FROM Table_Name GROUP BY Company,Route,date1) as CE ON TB.Company = CE.Company AND TB.Route = CE.Route
WHERE Rownumber = 1;

Related

SQL Order by date, then change the value of id with update function

This my first time when I use SQL and I need your help. I have got a table like this:
ID
date
1
01.02.2021
2
03.02.2021
3
04.02.2021
4
02.02.2021
And I can order it by date, then I have got this:
ID
date
1
01.02.2021
4
02.02.2021
2
03.02.2021
3
04.02.2021
I have done this with function UPDATE and ORDER BY. There is a question now. How to order by date, and change the value of ID with update function to get the result like this:
ID
date
1
01.02.2021
2
02.02.2021
3
03.02.2021
4
04.02.2021
Is there any quick method to sort by date and leave the order of ID? I want to help my friend with that but I have never been working with SQL. Sorry for my english.
Try following code
UPDATE table t
SET t.id = t1.NEW_ID
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [Date]) AS New_ID
FROM TABLE
) t1
Please try this,
with my_cte as (
select id, date
, row_number() over(order by date asc) rn
from test
)
update test set id =
(select min(rn) from my_cte
where test.id = my_cte.id and test.date=my_cte.date);

Get one record over period with condition

I have a big query creating a history of object changes. In short it result looks like this:
id changedOn recordtype
1 2019-12-5 history
1 2020-01-1 history
1 2020-01-7 actual
2 2018-10-9 history
The result I want:
id changedOn recordtype
1 2019-12-5 history
1 2020-01-7 actual
2 2018-10-9 history
If there is 2 records in the same month on each id I want to ommit history records for this Month.
I would like to avoid cursor if it possible. But I'm stuck.
If you want one record per month with a preference for "actual", then use row_number():
select t.*
from (select t.*,
row_number() over (partition by id, year(changedOn), month(changedOn) order by recordtype) as seqnum
from t
) t
where seqnum = 1;
If you want all "actual" records for a month -- and then if there are none -- all the history records, I would recommend logic like this:
select t.*
from t
where t.recordtype = 'actual' or
(t.recordtype = 'history' and
not exists (select 1
from t t2
where t2.id = t.id and
t2.recordtype = 'actual' and
year(t2.changedon) = year(t.changedon) and
month(t2.changedon) = month(t.changedon)
);
These two approaches are subtly different. But you will only notice the differences if you have multiple "actual"s or "history"s in a single month for a single id.
Just remove the records with changedOn that are not the most recent
select * from tbl a
where not exists
(select 1 from tbl b where a.id = b.id and a.recordtype = b.recordtype and a.changedOn < b.changedOn )

SQL retrieve recent record

I want to retrieve TOPIC 1 SCORES with the most recent score (excluding null) (sorted by date) for each detailsID, (there are only detailsID 2 and 3 here, therefore only two results should return)
What about getting rid of Topic 1 Scores in GROUP BYdetailsID,Topic 1 Scores ?
Use a subquery to get the max and then join to it.
SELECT a.detailsID,`Topic 1 Scores`, a.Date
FROM Information.scores AS a
JOIN (SELECT detailsID, MAX(Date) "MaxDate"
FROM Information.scores
WHERE `Topic 1 Scores` IS NOT NULL
GROUP BY detailsID) Maxes
ON a.detailsID = Maxes.detailsID
AND a.Date = Maxes.MaxDate
WHERE `Topic 1 Scores` IS NOT NULL
Assuming SQL Server:
SELECT
ROW_NUMBER() OVER (PARTITION BY detailsID ORDER BY Date DESC) AS RowNumber,
detailsID, Date, Topic 1 Scores
FROM
Information.scores
Try doing
SELECT detailsID,`Topic 1 Scores`, MAX(Date) as "Date" GROUP BY "Date"

SQL compare two max Dates from the same table

I dont know how to call this topic so I thought I just would explain what I need.
I have the following table:
Id IdPerson date successfully
1 1 01.01.2012 FALSE
2 1 01.01.2014 TRUE
3 2 01.01.2014 FALSE
Now I want all IdPerson where the newest entry is FALSE
So that would be just IdPerson 2 because IdPerson 1 is true in 2014.
I really have no clue how to do that.
Can somebody help me?
Greets
There is an interesting approach to this that uses conditional aggregation:
select idperson
from table t
group by idperson
having max(date) = max(case when successfully = 'false' then date end);
Note: this solution (as well as the others) assume that date is stored in a native date/time format. If not, you should fix the database, but this query would need to use convert().
If you are using SQL Server 2008 R2 (or higher), then you can use Apply
select p.* from Person P
cross Apply
(
select MAX(date) [maxdate] from Person group by Id
)a
where P.Date = a.maxdate and p.Successfully = 0
Use ROW_NUMBER() OVER (PARTITION BY ...) in a subquery to locate the newest entry per person. Then, in the outer query, select only those having successfully = 'FALSE':
SELECT Id, IdPerson, [date]
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY IdPerson ORDER BY [date] DESC) AS rn,
*
FROM MyTable ) t
WHERE t.rn = 1 AND t.successfully = 'FALSE'
I tried this in mysql:
SELECT Id,IdPerson,date,Status from MyTable
WHERE status='false' AND date= ALL( SELECT max(date) from MyTable
GROUP BY IdPerson);

Join two queries from the same table - SELECT DISTINCT?

I have two tables linked by an AUTO_KEY field, from one table I'm retrieving the number (id), from the other I get several statuses by number(id), each status has a date associated to it.
I need to restrict the results only to the maximum/latest date for all numbers(ids) and the corresponding status
SELECT
OPERATION.NUMBER,
STATUS.STATUS,
Max(STATUS.DATE)
FROM
STATUS,
OPERATION
WHERE
OPERATION.AUTO_KEY = STATUS.AUTO_KEY
From here
Number Status Date
-----------------------------
1 A 10/20/13
1 B 10/15/13
2 A 10/10/13
2 AX 10/05/13
2 AD 10/03/13
3 DD 10/03/13
The outcome should be
Number Status Date
-----------------------------
1 A 10/20/13
2 A 10/10/13
3 DD 10/03/13
Thanks in advance
You can use a CTE with ROW_NUMBER() function. Also Please use a Table JOIN instead FROM STATUS, OPERATION
;With CTE AS (
SELECT O.NUMBER, S.STATUS, S.DATE,
ROW_NUMBER() OVER (ORDER BY S.DATE DESC) RN
FROM STATUS S JOIN OPERATION O
ON O.AUTO_KEY = S.AUTO_KEY
)
SELECT NUMBER, STATUS, DATE
FROM CTE
WHERE RN = 1
ORDER BY NUMBER
SELECT OPERATION.CNUMBER,
STATUS.STATUS,
STATUS.CDATE
FROM STATUS,
OPERATION
WHERE OPERATION.AUTO_KEY = STATUS.AUTO_KEY
AND STATUS.CDATE = (
SELECT MAX(STATUS.CDATE) MAX_DATE
FROM STATUS,
OPERATION
WHERE OPERATION.AUTO_KEY = STATUS.AUTO_KEY
GROUP BY OPERATION.CNUMBER )