SQL statement to find Min Date - sql

I am new to SQL so I am fumbling here a bit. I have the following table:
Entered Generalist Item
12/31/2012 07:26:50 Tom Smith RTW/Updates
12/31/2012 07:30:10 Terrie Bradshaw Posters
12/31/2012 07:38:16 Jen Lopez Client Assistance/Request
12/31/2012 07:48:00 Tom Smith RTW/Updates
12/31/2012 07:50:29 Mike Smith RTW/Updates
12/31/2012 07:55:32 Tom Smith Client Assistance/Request
I am trying to find out when was the last time a rep was assigned an item. So I am looking for the Min value on a column. My query would look at Item "RTW/Updates" when was the earlier time entered between a date range and return Tom Smith. For example the user queries, RTW/Update between 12/31/2012 and 1/1/2013 and the answer would be Tom Smith.
This is what I have so far, but have not been able to figure out the between the dates part:
SELECT MIN(entered), generalist, item
FROM dataTable
That is pretty much it.

I May not understand what you want, but if you want to get one person back based on the minimum date, you need to work out the minimum date, and use that to find that person:
select
*
from
datatable
where
entered =
(
select
min(entered) as MinDate
from
DataTable
where
Item = 'RTW/Updates'
)
and item = 'RTW/Updates'
SQL Fiddle
You could also use a CTE:
; with LowDate as
(select
min(entered) as MinDate
from
DataTable
where
Item = 'RTW/Updates' )
select
*
from
datatable
inner join LowDate
ON entered = LowDate.MinDate
and item = 'RTW/Updates'
More SQL Fiddle!

You are looking for the window functions. Here is an example:
select generalist, item, entered
from (SELECT generalist, item, entered,
row_number() over (partition by item order by entered desc) as seqnum
FROM dataTable
) t
where seqnum = 1;
The function row_number() enumerates the rows for each item (based on the partition by clause) starting with 1. The row with 1 is going to have the most recent date, because of the order by clause.
The outer query just selects the rows where the seqnum = 1 -- which is the most recent record for each item.

I believe this should work (where the # variables are the parameters passed to your procedure)
SELECT MIN(entered), generalist, item
FROM dataTable
WHERE item = #itemParm
AND entered BETWEEN #enteredStart AND #enteredEnd
GROUP BY generalist, item

Use GROUP BY
SELECT MAX(entered) MinDate, generalist, item FROM dataTable
GROUP BY Generalist, Item

Just to add something to the answers (which are correct, essentially) before this one : in order to find the latest date, you'll have to use MAX() instead of MIN().

SELECT MIN(entered) MinDate, generalist, item
FROM dataTable
GROUP BY generalist, item
When you have used an aggregate function in your select statement and you are also selecting other column which are not contained in any aggregate function you have to tell sql server how to aggregate that column by adding a GROUP BY clause and mentioning names of all the column that are in SELECT statement but not contained in any Aggregate function.
to get the latest Date you will need to get the Biggest(Largest in Number Date) and you will need to use MAX() function instead of MIN(), MIN() will return the Oldest (smallest Date) in your column.
SELECT MAX(entered) MinDate, generalist, item
FROM dataTable
GROUP BY generalist, item

Related

How Can I Retrieve The Earliest Date and Status Per Each Distinct ID

I have been trying to write a query to perfect this instance but cant seem to do the trick because I am still receiving duplicated. Hoping I can get help how to fix this issue.
SELECT DISTINCT
1.Client
1.ID
1.Thing
1.Status
MIN(1.StatusDate) as 'statdate'
FROM
SAMPLE 1
WHERE
[]
GROUP BY
1.Client
1.ID
1.Thing
1.status
My output is as follows
Client Id Thing Status Statdate
CompanyA 123 Thing1 Approved 12/9/2019
CompanyA 123 Thing1 Denied 12/6/2019
So although the query is doing what I asked and showing the mininmum status date per status, I want only the first status date. I have about 30k rows to filter through so whatever does not run overload the query and have it not run. Any help would be appreciated
Use window functions:
SELECT s.*
FROM (SELECT s.*,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY statdate) as seqnum
FROM SAMPLE s
WHERE []
) s
WHERE seqnum = 1;
This returns the first row for each id.
Use whichever of these you feel more comfortable with/understand:
SELECT
*
FROM
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY statusdate) as rn
FROM sample
WHERE ...
) x
WHERE rn = 1
The way that one works is to number all rows sequentially in order of StatusDate, restarting the numbering from 1 every time ID changes. If you thus collect all the number 1's togetyher you have your set of "first records"
Or can coordinate a MIN:
SELECT
*
FROM
sample s
INNER JOIN
(SELECT ID, MIN(statusDate) as minDate FROM sample WHERE ... GROUP BY ID) mins
ON s.ID = mins.ID and s.StatusDate = mins.MinDate
WHERE
...
This one prepares a list of all the ID and the min date, then joins it back to the main table. You thus get all the data back that was lost during the grouping operation; you cannot simultaneously "keep data" and "throw away data" during a group; if you group by more than just ID, you get more groups (as you have found). If you only group by ID you lose the other columns. There isn't any way to say "GROUP BY id, AND take the MIN date, AND also take all the other data from the same row as the min date" without doing a "group by id, take min date, then join this data set back to the main dataset to get the other data for that min date". If you try and do it all in a single grouping you'll fail because you either have to group by more columns, or use aggregating functions for the other data in the SELECT, which mixes your data up; when groups are done, the concept of "other data from the same row" is gone
Be aware that this can return duplicate rows if two records have identical min dates. The ROW_NUMBER form doesn't return duplicated records but if two records have the same minimum StatusDate then which one you'll get is random. To force a specific one, ORDER BY more stuff so you can be sure which will end up with 1

SQL max without group by

I would like to get one row with the maximum date. I cannot use group by as I need to retrieve all data in that row.
I have this:
ID Date Country
1 05/05/2019 US
2 05/06/2019 UK
I want to get this:
ID Date Country
2 05/06/2019 UK
I've tried the below but it didn't work for me
select TOP 1 ID, Date, country
from table
order by Date desc
I don't believe you. Here is a db<>fiddle that shows three different interpretations of the date in your sample data:
as a string
as mm/dd/yyyy
as dd/mm/yyyy
All three of them produce the same result.
I suspect that your actual data is more complicated and you have oversimplified the example for the question. Further, my suspicion is that the date column is stored as a string rather than a date.
As a string, you might have some hidden characters that affect the sorting (such as leading spaces).
If this is the case, fix the data type and your code will work.
This depends on what DB system you are using.
In Microsoft SQL server, you can use row_number() function:
select top 1 *
from facts
order by ROW_NUMBER() over (order by dateKey)
Can you try this?
select Top 1 ID,Date, country from table where date = max(date)
First set the DATE or DATETIME Datatype in your [Date] column
then try this code:
SELECT TOP 1 ID, [Date] , country FROM TableName ORDER BY Date DESC
SELECT ID,Date,Country from TableName Where Date = MAX(Date) AND Rownum <= 1

Sum Sql is not working as expected result

I have a view that has values with total on each row plus the date.
I want to sum all the total for each date
V_stock
cd_client
qty
dt
v_stock_sum
select sum(qty), dt
from v_stock
group by (dt)
This gives a ridiculous number, what am i doing wrong, any tip helps thanks
V_stock
cd_client qty dt
LIMA 3360 2017-02-20
v_stock_sum
qty dt
120960 2017-02-20
I expected since there is one line only 3360
probably you have some problems with your view:
try to run count also to check if your view return more then one row
select sum(qty),
count(*) as rows,
dt
from v_stock
group by dt
if you will get more then 1 in the count then you need to check why you got more then one row
also you didn't put any condition on the cd_client
maybe you have only one row for each cd_client

SQL find nearest date without going over, or return the oldest record

I have a view in SQL Server with prices of items over time. My users will be passing a date variable and I want to return the closest record without going over, or if no such record exists return the oldest record present. For example, with the data below, if the user passes April for item A it will return the March record and for item B it will return the June record.
I've tried a lot of variations with Union All and Order by but keep getting a variety of errors. Is there a way to write this using a Case Statement?
example:
case when min(Month)>Input Date then min(Month)
else max(Month) where Month <= Input Date?
Sincere apologies for attaching sample dataset as an image, I couldn't get it to format right otherwise.
Sample Dataset
You can use SELECT TOP (1) with order by DATE DESC + Item type + date comparison to get the latest. ORDER BY will order records by date, then you get the latest either this month (if exists) or earlier months.
Here's a rough outline of a query (without more of your table it's hard to be exact):
WITH CTE AS
(
SELECT
ITEM,
PRICE,
MIN(ACTUAL_DATE) OVER (PARTITION BY ITEM ORDER BY ITEM) AS MIN_DATE,
MAX(INPUT_DATE<=ACTUAL_DATE) OVER (PARTITION BY ITEM ORDER BY ITEM,ACTUAL_DATE) AS MATCHED_DATE
FROM TABLE
)
SELECT
CTE.ITEM,
CTE.PRICE,
CASE
WHEN
CTE.MATCHED_DATE IS NOT NULL
THEN
CTE.MATCHED_DATE
ELSE
CTE.MIN_DATE
END AS MOSTLY_MATCHED_DATE
FROM CTE
GROUP BY
CTE.ITEM,
CTE.PRICE
The idea is that in a Common Table Expression, you use the PARTITION BY function to identify the key date for each item, record by record, and then you do a test in aggregate to pull either your matched record or your default record.

SQL Picking Top Date out of the Date Field

So I have a table with a date column. I want to be able to group these dates by Item field of some type. For example I might have a column called Item and within the Item field there may be 500 entries. Item 12345 might have 5 entires, each with a price. I want to be able to pull out all of the Items, grouped by the newest date.
031126-2M1 8/10/2011 12:00:00 AM 7.8678
031126-2M1 7/22/2011 12:00:00 AM 9.5620
031126-2M1 7/15/2011 12:00:00 AM 8.8090
In this example, I want to show the item with the closest date, 7/15/2011 so I can use that Price of 8.8090. The list would then show the other items, some may have one entry, others might have many, but I want to show all of them with the closets date. Need Help!
Thanks
A MS SQL Server version...
WITH
sorted_data AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY item_id ORDER BY item_date DESC) AS row_id,
*
FROM
item_data
WHERE
item_date <= getDate()
)
SELECT * FROM sorted_data WHERE row_id = 1
selct * from table
where This = that
Group by something having This.
order by date desc.
having "THIS" should be in the query itself.
hope this helps..
Cheers