TSQL - Best way to select data where a leave date falls in range of an invoice - tsql

Background: I have a payroll system where leave is paid only if it falls in range of the invoice being paid. So if the invoice covers the last 2 weeks then only leave in the last 2 weeks is to paid.
I want to write a sql query to select the leave.
Assume a table called DailyLeaveLedger which has among others a LeaveDate and Paid flag.
Assume a table called Invoice that was a WeekEnding field and a NumberWeeksCovered field.
Now assume week ending date 15/05/09 and NumberWeeksCovered = 2 and a LeaveDate of 11/05/09.
This is an example of how I want it written. The actual query is quite complex but I want the LeaveDate check to be a In subquery.
SELECT *
FROM DailyLeaveLedger
WHERE Paid = 0 AND
LeaveDate IN (SELECT etc...What should this be to do this)
Not sure if its possible the way I mention?
Malcolm

So LeaveDate should be between (WeekEnding-NoOfWeeksCovered) and (WeekEnding) for some Invoice?
If I've understood it right, you might be able to use an EXISTS() subquery, something like this:
SELECT *
FROM DailyLeaveLedger dl
WHERE Paid = 0 AND
EXISTS (SELECT *
FROM Invoice i
WHERE DateAdd(week,-i.NumberOfWeeksCovered,i.WeekEnding) < dl.LeaveDate
AND i.WeekEnding > dl.LeaveDate
/* and an extra clause in here to make sure
the invoice is for the same person as the dailyleaveledger row */
)

Related

MySQL Workbench - script storing return in array and performing calculations?

Firstly, this is part of my college homework.
Now that's out of the way: I need to write a query that will get the number of free apps in a DB as a percentage of the total number of apps, sorted by what category the app is in.
I can get the number of free apps and also the number of total apps by category. Now I need to find the percentage, this is where it goes a bit pear-shaped.
Here is what I have so far:
-- find total number of apps per category
select #totalAppsPerCategory := count(*), category_primary
from apps
group by category_primary;
-- find number of free apps per category
select #freeAppsPerCategory:= count(*), category_primary
from apps
where (price = 0.0)
group by category_primary;
-- find percentage of free apps per category
set #totals = #freeAppsPerCategory / #totalAppsPercategory * 100;
select #totals, category_primary
from apps
group by category_primary;
It then lists the categories but the percentage listed in each category is the exact same value.
I had initially thought to use an array, but from what I have read mySql does not seem to support arrays.
I'm a bit lost of how to proceed from here.
Finally figured it out. Since I had been saving the previous results in variables it seems that it was not able to calculate on a row by row basis, which is why all the percentages were identical, it was an average. So the calculation needed to be part of the query.
Here's what I came up with:
SELECT DISTINCT
category_primary,
CONCAT(FORMAT(COUNT(CASE
WHEN price = 0 THEN 1
END) / COUNT(*) * 100,
1),
'%') AS FreeAppSharePercent
FROM
apps
GROUP BY category_primary
ORDER BY FreeAppSharePercent DESC;
Then the query result is:

Compare 2 Tables When 1 Is Null in PostgreSQL

List item
I am kinda new in PostgreSQL and I have difficulty to get the result that I want.
In order to get the appropriate result, I need to make multiple joins and I have difficulty when counting grouping them in one query as well.
The table names as following: pers_person, pers_position, and acc_transaction.
What I want to accomplish is;
To see who was absent on which date comparing pers_person with acc_transaction for any record, if there any record its fine... but if record is null the person was definitely absent.
I want to count the absence by pers_person, how many times in month this person is absent.
Also the person hired_date should be considered, the person might be hired in November in October report this person should be filtered out.
pers_postition table is for giving position information of that person.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SELECT tr.create_time::date AS Date, pers.pin, tr.dept_name, tr.name, tr.last_name, pos.name, Count(*)
FROM acc_transaction AS tr
RIGHT JOIN pers_person as pers
ON tr.pin = pers.pin
LEFT JOIN pers_position as pos
ON pers.position_id=pos.id
WHERE tr.event_no = 0 AND DATE_PART('month', DATE)=10 AND DATE_PART('month', pr.hire_date::date)<=10 AND pr.pin IS DISTINCT FROM tr.pin
GROUP BY DATE
ORDER BY DATE
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
*This is report for octeber,
*Pin is ID number
I'd start by
changing the RIGHT JOIN for a LEFT JOIN as they works the same in reverse but it's confusing to figure them both in mind :
removing for now the pers_position table as it is used for added information purpose rather than changing any returned result
there is an unknown alias pr and I'd assume it is meant for pers (?), changing it accordingly
that leads to strange WHERE conditions, removing them
"pers.pin IS DISTINCT FROM pers.pin" (a field is never distinct from itself)
"AND DATE_PART('month', DATE)=10 " (always true when run in october, always false otherwise)
Giving the resulting query :
SELECT tr.create_time::date AS Date, pers.pin, tr.dept_name, tr.name, tr.last_name, Count(*)
FROM pers_person as pers
LEFT JOIN acc_transaction AS tr ON tr.pin = pers.pin
WHERE tr.event_no = 0
AND DATE_PART('month', pers.hire_date::date)<=10
GROUP BY DATE
ORDER BY DATE
At the end, I don't know if that answers the question, since the title says "Compare 2 Tables When 1 Is Null in PostgreSQL" and the content of the question says nothing about it.

Tableau: Getting Aggregate Count Based on Boolean Attributes

I am really new in Tableau and I would be needing help in some calculation.
My simplified data consists of three columns:
customer no, transaction date, lost_flag
here lost_flag is a boolean which marks as true if a customer made a transaction in the last 365 days.
(max([transaction date)< dateadd('year',-1,max([Report Date])))
I need to find the:
1. number of customers that are lost
2. number of customers that are not lost
3. attrition rate
For number one, I initially did
countd(if ([Lost_flag]) then [Customer No] else "" END)
But obviously it did not work.
Note: Customer_No is not unique here since this is a transactional sales data source
Thanks in advance.
First you need to make sure that your lost flag is being calculated at the customer level rather than the transaction level. In order to do this use the following formula, note that it is similar to yours however I have made it be fixed at customer id and also replaced report date with todays date:
Lost Flag = { FIXED [Customer ID]: (max([Transacton Date])<dateadd('year',-1,max(TODAY())))}
This will add a TRUE or FALSE flag against every transaction for a customer.It is important that this is fixed at the customer id level rather than the transaction otherwise all old transactions for a customer will be flagged as lost even if they have a recent transaction.
So in order to see how many customers are lost do the following:
1) drag lost_flag onto the rows shelf
2) drag customer id onto the text mark and then right click- measure - count distinct.

SQL - using the Min field to achieve desired result

Wondering the best SQL to handle below situation: Client only wants to see invoices that have been declined. I started with only show me when STATUS_ID = 2, but then realized that it was paid as it was resubmitted and accepted so that didn't work. What is the best way to handle 2 records like below where I don't want the SQL to return any records if manifest + order code have a 1. Would you do a Min on Status ID or something of that nature?
VENDOR NAME manifest ORDER_CODE STATUS_ID
VENDOR 12345 BHGSDKJF1234 RU07 2 (invoice decline)
VENDOR 12345 BHGSDKJF1234 RU07 1 (paid)
This trick can be work for you in this case, but it's not solve the general case (what happens if the STATUS_ID for paid is 3, and all possible values are 0-5?)
you can use in general SWICH-CASE clause, that gives you some 1 (true) if the client has STATUS_ID = 1, and 0 otherwise. Then, pick the MAX() for each invoice.
You can also consider another design that might work for you:
Add time\time-stamp column (Maybe, for your purpose, you can use SYSDATE time for insertion time of the record to db).
After you have a time column, you probably can choose the columns with the last time STATUS_ID for each invoice (get the STATUS_ID in the row with the max time).

SQL Reporting Services, filtering on Field not in DISTINCT SELECT statement?

I am using MS SQL Report Builder 3.0 to generate a report for SQL Reporting Services. I have a dataset that includes the columns AppointmentDate, PatientID, and InsuranceCarrier. I want to find out the number of DISTINCT patients that visited within a certain timeframe (begining AppointmentDate to ending AppointmentDate). The only time a patient should be present more than once in the query is if they had a different insurance carrier on a repeat visit.
If I perform the following query:
SELECT DISTINCT AppointmentDate, PaientID, InsuranceCarrier
FROM Encounters
WHERE AppointmentDate >= #beginningofdaterange
AND AppointmentDate <= #endofdaterange
Then I get a list of each patient and insurance carrier that visited in that date range. Unfortunately, since each AppointmentDate is also distinct, the Patients get duplicated for each individual appointment date. For example, if Patient X shows up twice in that timeframe specified, it will show both appointments.
If I remove the AppointmentDate from my SELECT statement, then under Dataset properties in the Report Builder 3.0 I can no longer Filter based on the AppointmentDate expression. I could do my filtering directly in the WHERE clause of the T-SQL statement, but that means I cannot use the run-time Report Parameters input by the user. This is a problem because I am filtering based on Report Parameters that the user selects when running the report. They input the starting AppointmentDate and a "18-months prior" Parameter is calculated as the beginning and end AppointmentDates to filter against.
So how do I include the AppointmentDate so that I can filter with it, but not include it in my DISTINCT SELECT so that it properly DISTINCTifies my data.
#FreefallGeek,
What do you mean by you can't filter AppointmentDate if you remove it from SELECT? Report Builder allows you do dataset filtering based on the user assigned parameter in run time with query like this,
SELECT DISTINCT PaientID, InsuranceCarrier
FROM Encounters
WHERE
AppointmentDate >= #beginningofdaterange
AND AppointmentDate <= #endofdaterange
With #beginningofdaterange and #endofdaterange as your report parameter. This should work unless you need to do additional filtering that require to return AppointmentDate as result.
If you really need to return the Appointment date as result or for additional filtering, then the next question is what should be the AppointmentDate when there are multiple visit with same patient and insurance carrier? The first visit or the last visit within the date range? If that is the case, you could use group by like this for first visit,
SELECT Min(AppointmentDate) AS FirstAppointmentDate, PaientID, InsuranceCarrier
FROM Encounters
WHERE
AppointmentDate >= #beginningofdaterange
AND AppointmentDate <= #endofdaterange
GROUP BY PaientID, InsuranceCarrier
ORDER BY AppointmentDate
However, from your description, it appears that you only need the distinct patient and insurance carrier with the capability to filter the date. If that understanding is correct, you could just filter the appointment with user input parameter in the WHERE clause without the SELECT.
In this particular case, I would take into account all visits per the entire day. And instead of displaying multiple encounters per patient per day, I would go to display for the report as AppointmentDate only the day part of the AppointmentDate itself. As the filtering might not need the exact moment of the visit, but only the fact that it took place. The resulting set would be then filtered by the report.
Your particular select would look like the following:
-- small modification (take encounters by entire day):
SELECT DISTINCT
CAST(e.AppointmentDate as Date) as AppointmentDateDay, -- the day of the visit
e.PatientID,
e.InsuranceCarrier,
COUNT(e.Id) as CntVisits -- display them if you'd like
FROM Encounters as e
WHERE AppointmentDate >= '20130624 10:00:00'
AND AppointmentDate <= '20130625 18:00:00'
GROUP BY PatientID, InsuranceCarrier, CAST(e.AppointmentDate as Date)
ORDER BY PatientId;
Example Fiddle - see both result sets.
If you really need to show the entire AppointmentDate to the user, I admit I don't have an idea now.