Return results based on datetime parameter - sql

I have a database table called Fees. In that table, I have FeeTypeEnum, EffectiveDate, and Amount columns.
Example of Table:
ID FeeTypeEnum EffectiveDate Amount
-----------------------------------------
1 1 1/1/2013 13.00
2 1 10/1/2013 98.36
3 2 4/1/2013 53.00
4 2 6/1/2013 51.00
5 3 7/1/2013 53.00
6 1 12/1/2012 12.00
How would I return only the results that would considered to be active based on the a datetime parameter date. For example: If today was 5/1/2013, only the following would be returned:
ID FeeTypeEnum EffectiveDate Amount
-----------------------------------------
1 1 1/1/2013 13.00
3 2 4/1/2013 53.00
I was thinking that I could just group them by FileTypeEnum and then remove the ones that are before the current date. Would that work?
Edit
Basically, I'm trying to return all the results where the EffectiveDate is BEFORE the datetime parameter and NOT the results where the EffectiveDate is AFTER the parameter.
Edit 2
When using the following query:
SELECT *
FROM [Fees]
WHERE [EffectiveDate] <= GETDATE()
ORDER BY [FeeEnum]
It also returns results for records that are no longer considered active. How would I select only 1 from each [FeeEnum] group?

Something like this?
SELECT *
FROM Fees
WHERE EffectiveDate <= #asOfDate
How you are calling the SQL (e.g. a stored procedure or directly form an application) will determine how to set the #asOfDate parameter.

New at this but I belive you want to bring back anything < systdate.
Try something like this:
SELECT *
FROM tablename
WHERE EffectiveDate<SYSDATE

Related

How to select Maximum and minimum date values and pass those as a query

I have a table with the following entries
CustomeID
TransDate
WorkID
1
2012-12-01
12
1
2012-12-03
45
1
2013-01-21
3
2
2012-12-23
11
3
2013-01-04
13
3
2013-12-24
16
4
2014-01-02
2
I am trying get the data between two dates and the required date values are minimum and maximum values of the column. I am able to get the desired output when I hard code the values.
SELECT *
FROM dbo.MyTable
WHERE TransDate >= '2012-12-01' AND TransDate <= '2014-01-02'
I am aware the if I remove the where clause it will solve all the issues, But my actual query is much complex and has other conditions. The only way is to get maximum date values and minimum date value from the table and pass that reference to it.
I tried the below step but that does not work and throws the below error.
SELECT *
FROM dbo.MyTable
WHERE TransDate >= '2012-12-01' AND TransDate <= MAX(TransDate)
Error
An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause or a select list, and the column being aggregated is an outer reference.
Expected Output:
CustomeID
TransDate
WorkID
1
2012-12-01
12
1
2012-12-03
45
1
2013-01-21
3
2
2012-12-23
11
3
2013-01-04
13
3
2013-12-24
16
4
2014-01-02
2
Use a scalar subquery to find the maximum date across the whole table:
SELECT *
FROM dbo.MyTable
WHERE TransDate >= '2012-12-01' AND
TransDate < (SELECT DATEADD(DAY, 1, MAX(TransDate)) FROM dbo.MyTable);
Note that I am using a strict inequality (less than) in the WHERE clause against one day later than the max date. This will include all days which fall on or earlier than the maximum date.
You can also declare variables and then use them as given below:
DECLARE #minDate DATE = (SELECT MIN(TransDate) FROM Customer);
DECLARE #maxDate DATE = (SELECT MAX(TransDate) FROM Customer);
SELECT * FROM dbo.MyTable WHERE TransDate >= #minDate AND
TransDate <= #maxDate

Get count of two different values but not same values

I have the following table format.
**ID Name Start Date End Date**
1 ABC 1/1/2015 12/31/2015
1 XYZ 4/1/2015 8/31//2015
1 DEF 1/1/2012 12/31/2012
2 ABC 1/23/2011 1/23/2012
2 ABC 1/31/2012 1/31/2013
3 DEF 2/12/2015 5/30/2015
3 XYZ 4/1/2015 6/01/2015
4 DEF 3/1/2015 12/31/2015
4 DEF 4/1/2015 6/30/2015
I need the count of ID's having Different Name which lies in date range of May 2015
Expected Results
ID COUNT
1 2
3 2
P.S - ID 4 also lies in the date range of MAY 2015, but the Name is same i.e DEF. So I need only ID's 1 and 3 but not 4.
Thank You in advance and appreciated for your efforts.
I imagine your sample data doesn't match your desired results, but I think this is what you're looking for using conditional aggregation:
select id, count(*)
from yourtable
group by id
having sum(case when '5/1/2015' between startdate and enddate then 1 else 0 end) > 1
and count(distinct name) = count(name)
SQL Fiddle Demo
The sum aggregation in the having clause is making sure there are multiple records in between that date. The count clause in the having clause is making sure there aren't any duplicates.
declare
#startdate datetime = '20150501',
#enddate datetime = '20150531'
select t.id, count(distinct t.name)
from mytable t
where t.startdate <= #enddate and t.enddate >= #startdate
group by t.id
having count(distinct t.name) > 1

Assign a counter in SQL Server to records with sequential dates, and only increment when dates not sequential

I am trying to assign a Trip # to records for Customers with sequential days, and increment the Trip ID if they have a break in sequential days, and come later in the month for example. The data structure looks like this:
CustomerID Date
1 2014-01-01
1 2014-01-02
1 2014-01-04
2 2014-01-01
2 2014-01-05
2 2014-01-06
2 2014-01-08
The desired output based upon the above example dataset would be:
CustomerID Date Trip
1 2014-01-01 1
1 2014-01-02 1
1 2014-01-04 2
2 2014-01-01 1
2 2014-01-05 2
2 2014-01-06 2
2 2014-01-08 3
So if the Dates for that Customer are back-to-back, it is considered the same Trip, and has the same Trip #. Is there a way to do this in SQL Server? I am using MSSQL 2012.
My initial thoughts are to use the LAG, ROW_NUMBER, or OVER/PARTITION BY function, or even a Recursive Table Variable Function. I can paste some code, but in all honesty, my code isn't working so far. If this is a simple query, but I am just not thinking about it correctly, that would be great.
Thank you in advance.
Since Date is a DATE (ie has no hours), you could for example use DENSE_RANK() by Date - ROW_NUMBER() days which will give a constant value for continuous days, something like;
WITH cte AS (
SELECT CustomerID, Date,
DATEADD(DAY,
-ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY Date),
Date) dt
FROM trips
)
SELECT CustomerID, Date,
DENSE_RANK() OVER (PARTITION BY CustomerID ORDER BY dt)
FROM cte;
An SQLfiddle to test with.

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.

Update the list of dates to have the same day

I have this in my table
TempTable
Id Date
1 1-15-2010
2 2-14-2010
3 3-14-2010
4 4-15-2010
i would like to change every record so that they have all same day, that is the 15th
like this
TempTable
Id Date
1 1-15-2010
2 2-15-2010 <--change to 15
3 3-15-2010 <--change to 15
4 4-15-2010
what if i like on the 30th?
the records should be
TempTable
Id Date
1 1-30-2010
2 2-28-2010 <--change to 28 because feb has 28 days only
3 3-30-2010 <--change to 30
4 4-30-2010
thanks
You can play some fun tricks with DATEADD/DATEDIFF:
create table T (
ID int not null,
DT date not null
)
insert into T (ID,DT)
select 1,'20100115' union all
select 2,'20100214' union all
select 3,'20100314' union all
select 4,'20100415'
SELECT ID,DATEADD(month,DATEDIFF(month,'20100101',DT),'20100115')
from T
SELECT ID,DATEADD(month,DATEDIFF(month,'20100101',DT),'20100130')
from T
Results:
ID
----------- -----------------------
1 2010-01-15 00:00:00.000
2 2010-02-15 00:00:00.000
3 2010-03-15 00:00:00.000
4 2010-04-15 00:00:00.000
ID
----------- -----------------------
1 2010-01-30 00:00:00.000
2 2010-02-28 00:00:00.000
3 2010-03-30 00:00:00.000
4 2010-04-30 00:00:00.000
Basically, in the DATEADD/DATEDIFF, you specify the same component to both (i.e. month). Then, the second date constant (i.e. '20100130') specifies the "offset" you wish to apply from the first date (i.e. '20100101'), which will "overwrite" the portion of the date your not keeping. My usual example is when wishing to remove the time portion from a datetime value:
SELECT DATEADD(day,DATEDIFF(day,'20010101',<date column>),'20100101')
You can also try something like
UPDATE TempTable
SET [Date] = DATEADD(dd,15-day([Date]), DATEDIFF(dd,0,[Date]))
We have a function that calculates the first day of a month, so I just addepted it to calculate the 15 instead...