Retrieve data using between some date range - sql

I have the following table in my database
Membership
ComapanyId
IsMember
JoinedDate
ExpiryDate
RejoinDate
LeavingDate
I am using the following query to return all the members as for 2011-01-31
select * from MEMBERSHIP
where (JoinedDate < '2011-01-31' or RejoinDate < '2011-01-31') and IsMember=1
My problem is it doesnt tally with the figures my manager has. Am I doing something wrong?

The problem is that IsMember is currently whether they are a member, not whether they were a member on 2011-01-31. So, your query is really answering the question: "Which members who were active today joined or last rejoined before 2011-01-31?"
For instance, someone who starts on 2011-01-30 and quits on 2011-02-01 would not count as a member in your query, but would be a member on that date.
The most accurate answer is to look in a transaction table for memberships, where you have joins and quits in the table.
Barring that, the following probably gets close enough:
select *
from MEMBERSHIP
where '2011-01-31' between JoinedDate and LeaveDate

Shouldn't you remove the "IsMember = 1" statement as you want to list users that were members before 2011-01-31 but are not members anymore? And maybe you should use '<=' if you want to include the 31th.
Also what is the default value of RejoinDate? If it is null it could have an influence on your WHERE statement...

The problem is that your date is implicitly treated as midnight of 2011-01-31 ('2011-01-31 00:00:00'), so any activity on that day is not included. Try using < '2011-02-01' instead, so that all of the activity on the 31st is included.

You clould use something like this:
JoinedDate <= CONVERT(Date, '2011-01-31')

Related

Why are different result between use date_part and exactly date parameter query data in peroid date?

I'm try to count distinct value in some columns in a table.
i have a logic and i try to write in 2 way
But i get diffent results from this two query.
Can any one help to clarify me? I dont know what wrong is code or i think.
SQL
select count(distinct membership_id) from members_membership m
where date_part(year,m.membership_expires)>=2019
and date_part(month,m.membership_expires)>=7
and date_part(day,m.membership_expires)>=1
and date_part(year,m.membership_creationdate)<=2019
and date_part(month,m.membership_creationdate)<=7
and date_part(day,m.membership_creationdate)<=1
;
select count(distinct membership_id) from members_membership m
where m.membership_expires>='2019-07-01'
and m.membership_creationdate<='2019-07-01'
;
I actually think that this is the query you intend to run:
SELECT
COUNT(DISTINCT membership_id)
FROM members_membership m
WHERE
m.membership_expires >= '2019-07-01' AND
m.membership_creationdate < '2019-07-01';
It doesn't make sense for a membership to expire at the same moment it gets created, so if it expires on midnight of 1st-July 2019, then it should have been created strictly before that point in time.
That being said, the problem with the first query is that, e.g., the restriction on the month being on or before July would apply to every year, not just 2019. It is difficult to write a date inequality using the year, month, and day terms separately. For this reason, the second version you used is preferable. It is also sargable, meaning that an index on membership_expires or membership_creationdate can be used.
There is an issue with the first query:
select count(distinct membership_id) from members_membership m
where date_part(year,m.membership_expires)>=2019
and date_part(month,m.membership_expires)>=7
and date_part(day,m.membership_expires)>=1
and date_part(year,m.membership_creationdate)<=2019
and date_part(month,m.membership_creationdate)<=7
and date_part(day,m.membership_creationdate)<=1; -- do you think that any day is less than 1??
-- this condition will be satisfy by only 01-Jul-2019, But I think you need all the dates before 01-Jul-2019
and date_part(day,m.membership_creationdate)<=1 is culprit of the issue.
even membership_creationdate = 15-jan-1901 will not satisfy above condition.
You need to always use date functions on date columns to avoid such type of issue. (Your second query is perfectly fine)
Cheers!!
The reason could be due to a time component.
The proper comparison for the first query is:
select count(distinct membership_id)
from members_membership m
where m.membership_expires >= '2019-07-01' and
m.membership_creationdate < '2019-07-02'
--------------------------------^ not <= ---^ next day
This logic should work regardless of whether or not the "date" has a time component.

SQL query to search 3 date fields

I'm trying to run a query against 3 different fields. I want it to return all the accounts that meet the first range, bring back all accounts that meet the second range and same for the third. I tried using and but get dates outside of the range.
select
*
from
Permits
where
created between '1/1/2015' and '1/21/2015'
and updated between '1/1/2015' and '1/21/15'
and noResponseDateSet between '1/1/15' and '1/21/15'
order by
alarmNo
Thanks for helping me
Use ISO standard date formats:
select created, updated, noResponseDateSet
From Permits
where created between '2015-01-01' and '2015-01-21' and
updated between '2015-01-01' and '2015-01-21' and
noResponseDateSet between '2015-01-01' and '2015-01-21' ;
This should fix the problem, unless you have one combination of rather arcane international date settings.
CONVERT can do the dirty parsing work for you. It will accept 1/1/2015 or 01-01-2015 or most other combinations.
select *
From Permits
where created between CONVERT(DATETIME,'1/1/2015') and CONVERT(DATETIME,'1/21/2015')
and updated between CONVERT(DATETIME,'1/1/2015') and CONVERT(DATETIME,'1/21/15')
and noResponseDateSet between CONVERT(DATETIME,'1/1/15') and CONVERT(DATETIME,'1/21/15')
order by alarmNo

Getting Dates only less than a particular date using date functions

I have a table called tableA with TrasactionDate as one field. I have a particular date called myfixeddate (say it's 2014-03-08).
I want to get the TransactionDate within 4 months, but only before my fixed date myfixeddate ('2014-03-08') from the tableA. Say my query should give '2014-03-06','2014-03-05','2014-02-01',....
But when I use the following query :
SELECT TrasactionDate
FROM tableA
WHERE datediff(mm,Transdate,myfixeddate) < 4
It gives the TransactionDate in both ways (before and after). That means the result gave '2014-03-10','2014-03-18' with the wanted ones like '2014-03-05',....
Could you please tell me how to prevent this and what code I need to use to get the TransactionDate in one direction?
You may try like this:
Select TrasactionDate from tableA
where [TrasactionDate] between DATEADD(month, -4, myfixeddate) and myfixeddate

Postgresql query between date ranges

I am trying to query my postgresql db to return results where a date is in certain month and year. In other words I would like all the values for a month-year.
The only way i've been able to do it so far is like this:
SELECT user_id
FROM user_logs
WHERE login_date BETWEEN '2014-02-01' AND '2014-02-28'
Problem with this is that I have to calculate the first date and last date before querying the table. Is there a simpler way to do this?
Thanks
With dates (and times) many things become simpler if you use >= start AND < end.
For example:
SELECT
user_id
FROM
user_logs
WHERE
login_date >= '2014-02-01'
AND login_date < '2014-03-01'
In this case you still need to calculate the start date of the month you need, but that should be straight forward in any number of ways.
The end date is also simplified; just add exactly one month. No messing about with 28th, 30th, 31st, etc.
This structure also has the advantage of being able to maintain use of indexes.
Many people may suggest a form such as the following, but they do not use indexes:
WHERE
DATEPART('year', login_date) = 2014
AND DATEPART('month', login_date) = 2
This involves calculating the conditions for every single row in the table (a scan) and not using index to find the range of rows that will match (a range-seek).
From PostreSQL 9.2 Range Types are supported. So you can write this like:
SELECT user_id
FROM user_logs
WHERE '[2014-02-01, 2014-03-01]'::daterange #> login_date
this should be more efficient than the string comparison
Just in case somebody land here... since 8.1 you can simply use:
SELECT user_id
FROM user_logs
WHERE login_date BETWEEN SYMMETRIC '2014-02-01' AND '2014-02-28'
From the docs:
BETWEEN SYMMETRIC is the same as BETWEEN except there is no
requirement that the argument to the left of AND be less than or equal
to the argument on the right. If it is not, those two arguments are
automatically swapped, so that a nonempty range is always implied.
SELECT user_id
FROM user_logs
WHERE login_date BETWEEN '2014-02-01' AND '2014-03-01'
Between keyword works exceptionally for a date. it assumes the time is at 00:00:00 (i.e. midnight) for dates.
Read the documentation.
http://www.postgresql.org/docs/9.1/static/functions-datetime.html
I used a query like that:
WHERE
(
date_trunc('day',table1.date_eval) = '2015-02-09'
)
or
WHERE(date_trunc('day',table1.date_eval) >='2015-02-09'AND date_trunc('day',table1.date_eval) <'2015-02-09')

SQL Server Query Explanation

I am working on code from a person who held my position 2+ years ago, and am having trouble deciphering a block of their SQL code.
WHERE ACCOUNT NOT IN (SELECT ACCOUNT
FROM MWAPPTS A1
WHERE A1.ACCOUNT = A.ACCOUNT
AND ADATE > dbo.Endofmonth(ACTIONDATE)
AND REASON IN ('CPE','NPPE')
AND USERFLAG IN ( 'U', 'B' ))
dbo.Endofmonth is a stored procedure which gets the last day of the month for the inputed date.
If I am reading that right, we are not including rows where the account would be returned by the select statement shown. I am having problems with the select statement though. Am I correct that it is getting ACCOUNT where ADATE is older than the end of the month. The reason IS "CPE" or "NPPE", and the USERFLAG is either "U", or "B"?
Yes, you are returning the records where the account does not have the following:
1) an ADATE greater than the date returned by the function dbo.Endofmonth(ACTIONDATE).
2) a Reason that is CPE or NPPE
3) and the Userflag is either U or B.
You would have to look at the code in the function dbo.Endofmonth(ACTIONDATE) to determine exactly what it is returning.
Am I correct that it is getting ACCOUNT where ADATE is older than the end of the month.
The inner SELECT itself is looking for entries where ADATE is after the end of the month from ACTIONDATE. The NOT IN in the outer SELECTshould then retrieve rows where the account's ADATE is <= the end of the month from ACTIONDATE.
Your other assumptions seem correct.
Aside: It seems dbo.Endofmonth is a User-Defined Function, not a stored procedure (or it wouldn't be possible to call it like that).