Link to home
Start Free TrialLog in
Avatar of Brook_Lane
Brook_LaneFlag for United States of America

asked on

Date BETWEEN clause being ingored in complex query with JOINS

Hello,

I am attempting to add two date paramaters to an existing query using a "between" clause like this:

AND TIMES.ADMINISTERED_TIME between '2017-01-01' and '2018-01-01'

Open in new window


The problem is that this part seems to get ignored (doesn't change the results of the query) when added.  

I do not receive any errors and I have tried various ways of referencing the ADMINISTERED_TIME field with not avail.

The following query (for testing) works as expected:

SELECT * FROM  ORDER_MED_ADMIN_TIMES WHERE ADMINISTERED_TIME BETWEEN '2017-01-01' AND '2018-01-01'

Open in new window


Here is the entire query where the date between clause has no effect:

SELECT
DISTINCT 
ORD.CLIENTID ||' '|| TRIM(CLTLST)||', '||TRIM(CLTFST) AS CLIENT
, Case when varchar_format (stopdatetime, 'YYYY-MM-DD HH24:MI') >= varchar_format (I.CHANGESTAMP, 'YYYY-MM-DD HH24:MI') then 'discharged' else ORD.STATUS end as STATUS
,UPPER(BRAND_NAME) AS TEST
,TRIM(BRAND_NAME)||' ('||TRIM(GENERIC_NAME)||') '||TRIM(STRENGTH) AS MEDICATION
,TRIM(SIG_ACTION)||' '|| TRIM(SIG_DOSE)||' '|| TRIM(SIG_DOSE_UNIT)||' '|| TRIM(SIG_ROUTE)||' '|| TRIM(SIG_DOSE_TIMING)||' '|| TRIM(SIG_DOSE_OTHER)||' '|| TRIM(SIG_DOSE_OTHER) AS SIG
, DATE(SCHEDULEDSTARTDT) AS START_DATE
, DATE(SCHEDULEDENDDT) AS END_DATE
, DATE(I.DISCHARGEDATE) as INPATIENT_DISCHARGE
,TRIM(INSTRUCTIONS) AS INSTRUCTION
,TRIM(STAFF.SMMLNM) ||', '|| TRIM(STAFF.SMMFNM) AS ORDERING_STAFF
,TRIM(STAFF2.SMMLNM) ||', '|| TRIM(STAFF2.SMMFNM) AS AUTHORIZING_STAFF
,TRIM(STAFF3.SMMLNM) ||', '|| TRIM(STAFF3.SMMFNM) as MODIFYING_STAFF
FROM ORDERS ORD 
	LEFT OUTER JOIN CLTMSTPF CLT ON ORD.CLIENTID = CLT.CLTCAS 
	LEFT OUTER JOIN ORDER_MED_ADMIN_TIMES TIMES ON ORD.UID = TIMES.ORDER_ID
	LEFT OUTER JOIN EMAR_ACTIONS ON EMAR_ACTIONS.UID = TIMES.EMAR_ACTION
	LEFT OUTER JOIN RCOPIA_MEDICATIONS MED ON MED.RCOPIA_ID = ORD.RCOPIA_ID 
	LEFT OUTER JOIN RCOPIA_DRUGS DRUG ON DRUG.RCOPIA_DRUG_ID = MED.RCOPIA_DRUG_ID
	LEFT OUTER JOIN STAFFMSTR STAFF ON STAFF.SMMNUM = ORD.ORDERING_STAFF 
	LEFT OUTER JOIN STAFFMSTR STAFF2 ON STAFF2.SMMNUM = CREATED_USER
	LEFT OUTER JOIN STAFFMSTR STAFF3 ON STAFF3.SMMNUM = MODIFY_USER
	LEFT OUTER JOIN DOCTSK DOC ON DOC.CLIENT_ID = CLT.CLTCAS AND UPPER(DOC.FORM_ID) = 'SHIFT NOTES' AND UPPER(DOC.STATUS) = 'NEW' --AND DOC.EVETRN_ID <> 0
	JOIN INPATIENTEPISODES I on I.UID = (Select MAX (UID) from INPATIENTEPISODES where CLIENTID = ORD.CLIENTID and DISCHARGEDATE is not null)

	WHERE ORD.ORDERTYPEID = 3 


AND TIMES.ADMINISTERED_TIME between '2017-01-01' and '2018-01-01'


AND BRAND_NAME LIKE '%nitrofurantoin' 
OR BRAND_NAME LIKE '%cephalexin'
OR BRAND_NAME LIKE '%amoxicillin'
OR BRAND_NAME LIKE '%clindamycin'
OR BRAND_NAME LIKE '%mupirocin'
OR BRAND_NAME LIKE '%sulfamethoxazole'
OR BRAND_NAME LIKE '%amox'
OR BRAND_NAME LIKE '%azithromycin'
OR BRAND_NAME LIKE '%valacyclovir'
OR BRAND_NAME LIKE '%cefuroxime'
OR BRAND_NAME LIKE '%minocycline'
OR BRAND_NAME LIKE '%fluconazole'
OR BRAND_NAME LIKE '%levofloxacin'
ORDER BY UPPER(BRAND_NAME) ASC

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Sujith
Sujith
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Brook_Lane

ASKER

That was the problem - SOLVED!  Thank you!
Just a note, no more.

While it seems like "between" is useful for date ranges, in fact it can be plain wrong. In SQL "between" is just an abbreviation for the following:

AND DATE(ORD.SCHEDULEDSTARTDT) >= '2017-01-01' and  DATE(ORD.SCHEDULEDSTARTDT) <= '2018-01-01'

The problem is that there are 2 equal signs! and what you will get is every for the year 2017 PLUS ALL OF '2018-01-01' as well

A much more accurate way of defining you date range is this:

AND ORD.SCHEDULEDSTARTDT >= '2017-01-01' and  ORD.SCHEDULEDSTARTDT < '2018-01-01'

Note that you also do not need DATE() either, just leave the data untouched by that function, it will NOT help.

If (for some strange reason) you really do want one year and one day of data, then all you need to do is move the later date to to the next day:

AND ORD.SCHEDULEDSTARTDT >= '2017-01-01' and  ORD.SCHEDULEDSTARTDT < '2018-01-02'


Please don't use between for date ranges, it has the potential of getting you into trouble. Way better to use the direct >= and < operators. For more on this topic please see: "Beware of Between"

the best practice with date and time ranges is to avoid BETWEEN and to always use the form:

WHERE col >= '20120101' AND col < '20120201'
This form works with all types and all precisions, regardless of whether the time part is applicable.
Itzik Ben-Gan