No Records Returned in Left Join with Inequality in MS Access - left-join

Description
Hi,
I have a query using the same table twice in a left join with a inequality, but it does not produce any records, even though I am using a left join. I use MS Access 2013.
Code
The code is:
SELECT DCT01A.*,
DCT01B.*
FROM utb_DCT_01_DailyConversionTrends AS DCT01A
LEFT JOIN utb_DCT_01_DailyConversionTrends AS DCT01B
ON DCT01A.[Hour] = DCT01B.[Hour]
AND DCT01A.[WeekDay] = DCT01B.[WeekDay]
AND DCT01A.[Specification] = DCT01B.[Specification]
AND INT(DCT01A.[Date]) > INT(DCT01B.[Date])
Data
I am expecting (at the moment, though this will change later) that an inner join would result in no records produced. This is due to that this is only test data and the dates only span two days.
Hour and WeekDay refers to the current the hour of the day and the week day number in the week. Specification is an ID. Date is that date, which include time.
Goal
My goal of this query is to find all previous data on the same week day and hour, without picking the current record again (hence an inequality).
I realise I can simply run the inequality as >= instead, and then remove the = records afterwards. So I do have a simple workaround, I just can't understand why it won't work when written as above.
Thank you all for looking at this.

Would this work for you?
SELECT * FROM
(
SELECT DCT01A.*,
DCT01B.*
FROM utb_DCT_01_DailyConversionTrends AS DCT01A
LEFT JOIN utb_DCT_01_DailyConversionTrends AS DCT01B
ON DCT01A.[Hour] = DCT01B.[Hour]
AND DCT01A.[WeekDay] = DCT01B.[WeekDay]
AND DCT01A.[Specification] = DCT01B.[Specification]
AND INT(DCT01A.[Date]) >= INT(DCT01B.[Date])
)
WHERE
DCT01A.[Date] <> DCT01B.[Date]
Kindest regards..

Related

How to get data according to a user defined date in Tableau?

I am creating a tableau dashboard and it should load data according to the date the user enters. This is the logic that I am trying.
select distinct XX.ACCOUNT_NUM, (A.TOTAL_BILLED_TOT-A.TOTAL_PAID_TOT)/1000 arrears, ((A.TOTAL_BILLED_TOT-A.TOTAL_PAID_TOT)/1000 - XX.SUM_BILL ) TILL_REF_JUL20
FROM
(
select /*+ parallel (bill ,40 ) */ distinct account_num, sum(INVOICE_NET_mny + INVOICE_TAX_mny)/1000 SUM_BILL
from bill
where account_num in (Select account_num from MyTable)
and trunc(bill_dtm) > ('07-Aug-2021') –-Refmonth+1 month and 07 is a constant. Only month and year is changing
and cancellation_dtm is null
group by account_num
)xx , account a
where xx.ACCOUNT_NUM = A.account_num
Here is what I tried. First created a parameter called ref_Month. Then created a calculated field with this.
[Ref_Month]=MAKEDATE(DATETRUNC('year',(DATEADD('month', 1, [Ref_Month])), 07))
But I am getting an error. I am using a live connection. Is there any method to achive this?
I don't understand what this statement is trying to do:
[Ref_Month]=MAKEDATE(DATETRUNC('year',(DATEADD('month', 1, [Ref_Month])), 07))
If Ref_Month is a date, which it has to be for DATEADD to be a valid operation, why not make it the 7th of whatever starting month and year you are starting with? Then DATEADD('month',1, [Ref_Month]) will be a month later, still on the 7th. So you don't need DATETRUNC or MAKEDATE at all.
That said, how, when, and where are you trying to COMPUTE a PARAMETER,
let alone based on itself?

Excluding date(s) from a report

Monday this week (26th August) was a public holiday in the UK. I need to exclude this date from some of my reports.
Simple enough but I have one database where the date is broken into 15 minute segments, for example:
2019-08-26 08:30:00.000
2019-08-26 16:15:00.000
The only way I can work out to exclude all these dates from the report would be to use NOT IN, for example:
AND a.mydate NOT IN ('2019-08-26 08:30:00.000', '2019-08-26 16:15:00.000')
Which seems quite a ponderous way of doing it to me.
There's also:
and a.mydate NOT BETWEEN '2019-08-26 08:30:00.000' and '2019-08-26 19:30:00.000'
but any advance on that would be useful to know about, if there is an advance on this, as there will be more, perhaps many more, public holidays to exclude, moving forwards.
I do not have a separate table with holiday dates in it, so I need to script as per the above.
Thank you
If you have discreet values, you could add them to a table and do a left join and put a filter in WHERE saying the exclusion table's Id should be null (meaning the join failed).
Sth like:
SELECT
mydata
FROM
mytable mt LEFT JOIN Holidays h ON mt.mydate = h.date
WHERE
h.Id IS NULL
This is just an alternative way made possible because you have discrete values, I'm not sure if it's actually faster or not...
This worked better:
and cast(a.mydate as date) not in
( '2019-08-26',
'2019-12-25',
'2019-12-26',
'2020-01-01',
. . . )

Year over year monthly sales

I am using SQL Server 2008 R2. Here is the query I have that returns monthly sales totals by zip code, per store.
select
left(a.Zip, 5) as ZipCode,
s.Store,
datename(month,s.MovementDate) as TheMonth,
datepart(year,s.MovementDate) as TheYear,
datepart(mm,s.MovementDate) as MonthNum,
sum(s.Dollars) as Sales,
count(*) as [TxnCount],
count(distinct s.AccountNumber) as NumOfAccounts
from
dbo.DailySales s
inner join
dbo.Accounts a on a.AccountNumber = s.AccountNumber
where
s.SaleType = 3
and s.MovementDate > '1/1/2016'
and isnull(a.Zip, '') <> ''
group by
left(a.Zip, 5),
s.Store,
datename(month, s.MovementDate),
datepart(year, s.MovementDate),
datepart(mm, s.MovementDate)
Now I'd like to add columns that compare sales, TxnCount, and NumOfAccounts to the same month the previous year for each zip code and store. I also would like each zip code/store combo to have a record for every month in the range; so zeros if null.
I do have a calendar table that I tried to use to get all months, but I ran into problems because of my "where" statements.
I know that both of these issues (comparing to previous year and including all dates in a date range) have been asked and answered before, and I've gotten them to work before myself, but this particular one has me running in circles. Any help would be appreciated.
I hope this is clear enough.
Thanks,
Tim
Treat the Query you have above as a data source. Run it as a CTE for the period you want to report, plus the period - 12 months (to get the historic data). (SalesPerMonth)
Then do a query that gets all the months you need from your calendar table as another CTE. This is the reporting months, not the previous year. (MonthsToReport)
Get a list of every valid zip code / Store combo - probably a select distinct from the SalesPerMonth CTE this would give you only combos that have at least one sale in the period (or historical period - you probably also want ones that sold last year, but not this year). Another CTE - StoreZip
Finally, your main query cross joins the StoreZip results with the MonthsToReport - this gives you the one row per StoreZip/Month combos you are looking for. Left join twice to the SalesPerMonth data, once for the month, once for the 1 year previous data. Use ISNULL to change any null records (no data) to zero.
Instead of CTEs, you could also do it as separate queries, storing the results in Temp tables instead. This may work better for large amounts of data.

Optimizing a WHERE clause with a dateadd function

For the business that I am working in I would like to get information on our customers. The base information I have on these customers is as follows:
Activation_Date stored in a Loans table, datatype is datetime.
ActivityDate stored in a CustomerDailyLoanActivity_Information table (a daily loans table to those interested, it is part of a datamart and stores for each day that a customer has been active with our company how much they have paid into their loan, so if a customer has an Activation_Date of 15-03-2017, it has ActivityDates in the CustomerDailyLoanActivity_Information table from 15-03-2017 up until now whereby each ActivityDate has a record in another column Sum_Paid_To_Date how much has been paid up until that ActivityDate). Datatype of ActivityDate is date.
What I would like to know is the following, I would like to know how much each customer has paid on 1, or 2, or 3, etc. months after his Activation_Date. So the query would look something like the following (slightly pseudo-code, the more important part is the WHERE clause).
SELECT
cldai.Sum_Paid_To_Date,
cldai.ActivityDate,
cldai.Customer_Account_Number
FROM
CustomerLoanDailyActivity_Information cldai
INNER JOIN
Loans l ON l.Customer_Account_Number = cldai.Customer_Account_Number
WHERE
(cldai.ActivityDate = CAST(l.Activation_Date AS date)
OR
cldai.ActivityDate = DATEADD(month, 1, CAST(l.Activation_Date AS date))
OR
cldai.ActivityDate = DATEADD(month, 2, CAST(l.Activation_Date AS date))
OR
cldai.ActivityDate = DATEADD(month, 3, CAST(l.Activation_Date AS date))
)
ORDER BY
l.Customer_Account_Number, cldai.ActivityDate ASC
So the problem is that this query is really really slow (because of the WHERE clause and because the cldai table is big (~6 GB)) and exits before any data is retrieved. A couple of problems that I have heard, and possible solutions, but haven't worked so far.
The CAST function makes the query really slow because it does a comparison with the ActivityDate column, which is indexed. I used CONVERT before but that was also really slow. I feel like I need to do the convert/cast though, because the ActivityDate is of date type and the Activation_Date is of datetime type, so there is a possibility that the time part of the datetime in Activation_Date will cause there to be no matches with the ActivityDate (e.g. Activation_Date for a given customer is 15-03-2017 09:00:00 so it will never match with ActivityDate 15-03-2017 because this might be converted to datetime 15-03-2017 00:00:00, which will never be equal because of the time part).
I have to use "DateTime" evaluations, which has been suggested as a solution, but I have no clue on how to apply this correctly.
I can't look at the execution plan because the DBA has blocked me from seeing that.
Any ideas on how to make this query perform more quickly? Any help would be greatly appreciated.
So a massive speedup was obtained by using a LEFT JOIN instead of an INNER JOIN and by not ordering the data on the server but on the client side. This reduced the query time from about an hour and 10 minutes to about 1 minute. It seems unbelievable but it's what happened.
Regards,
Tim.
If you are guaranteed to have a record for each day, you could apply use the row_number() function to apply row numbers for each group of customer loan repayment records, and then retrieve rows 1,31,61 and 91? This would avoid any date manipulation.
How about splitting this up into two steps? Step one - build a table with the four dates for each customer. Then step two, join this to your main CustomerLoanDailyActivity_Information table on date and customer account number. The second step would have a much simpler join, just an = between the ActivityDate and date entry in the table you have built.

POSTGRESQL Comparing a time overlap across rows

I'm creating a query in our EHR. I am looking for patients that have accounts that are within 48 hours of each other to make sure they aren't coming back in with the same symptoms.
to work with i have the following columns in two tables
visit table
'patnum' which is the unique number attached to each visit
'mr_num' which is the unique number attached to each patient
.
er_log table
'patnum' which is the unique number attached to each visit
arrivaldt and arrivaltime which i will unite in a timestamp and is when the patient presented themselves
dischargedate and dischargetime which I will unite in a timestamp and is when the patient was discharged
1.what are some methods for comparing the arrivaltime and dischargetime across all of an mr_num's accounts and finding those with less than 48 hours of difference?
thanks!
edit: my explanation may be a little vague
example pt with MR num '334455' is a frequent flyer at the ER. she has come in 25 times in the last 7 months. each of those visits has a unique patnum, an arrivaldate and a discharge date. I am trying to find if any of her visits happened within 48 hours of each other by comparing one visits date with every other visits arrival date. query will report those visits that are within 48hours of each other.
I'm assuming that dischargetime and arrivaltime are of type timestamp to simplify the code, but you can always do the conversion on your own.
Previous answer
Use INNER JOIN to connect with table containing your times. Assuming that a patient can be discharged only after he presented himself, you can subtract arrivaltime from dischargetime to receive result in INTERVAL type and get back only those rows where they differ by maximum 2 days, which is 48 hours.
SELECT
v.mr_num, v.patnum
FROM
visit v
INNER JOIN er_log e USING ( patnum )
WHERE
v.mr_num = ?
AND e.dischargetime - e.arrivaltime < interval '2 days'
To get some deeper understanding you could look into SQL Fiddle I've created.
Current answer
Changes in code after comment and edited question. This will scan all visits for a particular patient and return those that happened within 2 days from the end of any of previous visits. You may want to change logic a bit with the line where the comparison takes place, to better suit your need
AND e1.dischargetime - e2.arrivaltime < interval '2 days'
and decide whether you base your times on arrivaltime or dischargetime for the current visit being compared and all the visits that are in a lookup.
SELECT
v.mr_num, v.patnum
FROM
visit v1
INNER JOIN er_log e1 USING ( patnum )
WHERE
v.mr_num = ?
AND EXISTS (
SELECT 1
FROM visit v2
INNER JOIN er_log e2 USING ( patnum )
WHERE
v1.mr_num = v2.mr_num
AND v1.patnum IS DISTINCT FROM v2.patnum
AND e1.dischargetime - e2.arrivaltime < interval '2 days'
)
What you will need to do is do TWO inner joins to the ER_LOG table. I'm going to borrow the previous answer and extend it:
SELECT
v1.mr_num, v1.patnum, v2.patnum,
(e1.dischargetime - e2.arrivaltime) as elapsed
FROM
visit v1
INNER JOIN er_log e1 on (v1.patnum = e1.patnum)
INNER JOIN visit v2 on (v1.mr_num = v2.mr_num and v1.patnum <> v2.patnum)
INNER JOIN er_log e2 on (v2.patnum = e2.patnum)
WHERE
v1.mr_num = ?
AND e1.dischargetime - e2.arrivaltime < interval '2 days'
You must join against the er_log table twice to get the two different visits so that you can compare times. You must also join against visit again to establish visits for the same patient (mr_num), and you may exclude the identical visit by making sure the patnum values are different.