Join check view with a calendar view - sql

I have two views. One with checks:
Check_Id Issued_Date Cleared_Date Amount
1 2017.01.03 2017.02.04 100
2 2017.03.03 2017.04.04 100
3 2017.08.03 100
...
And another is just a calendar:
Day
2001.01.01
2001.01.02
2001.01.03
...
2100.12.31
I need a scaffold view for Tableau. What i'd like to achieve is, for every check, have a record in the dates between Issued date to the cleared date. If there is no cleared date, just go to the end of times (2100.12.31 in this case).
Ie, for the Check_id 1:
Day Check_ID
2017.01.03 1
2017.01.03 1
2017.01.03 1
2017.01.03 1
...
2017.02.04 1
2017.08.03 3
2017.08.04 3
2017.08.05 3
2017.08.06 3
...
2100.12.31 3
Any tip or stuff i'd read to get it? Thanks!

This is a non-equijoin:
select ca.day, c.check_id
from checks c join
calendar ca
on ca.day >= c.issued_date and
(c.cleared_date is null or c.cleared_date >= ca.date);

Related

Finding the exact overlapping time

with tickets as (
select o.SSTID, o.open_Id, o.Createddatetime openTime, c.Createddatetime closeTime
from dbo.Close_ticket c
inner join dbo.Openticket o ON o.SSTID = c.SSTID and c.Open_ID=o.open_id
)
select t1.SSTID,
SUM(isnull(datediff(hour
, case when t1.openTime > t2.openTime then t1.openTime else t2.openTime end
, case when t1.closeTime > t2.closeTime then t2.closeTime else t1.closeTime end),0)) as [OverLappingtime]
from tickets t1
left join tickets t2 on t1.SSTID = t2.SSTID
and t1.openTime < t2.closeTime and t2.openTime < t1.closeTime
and t1.open_id < t2.open_id
group by t1.SSTID
This is my code where each ticket is compared to every other ticket to find the total overlapping time. But if I create more tickets the total time exceeds 24 hours when all the tickets where created on the same day. How can I find the exact overlapping time? If we see the first three tickets, the 2nd and the third ticket were opened and closed within the opening and closing time of the first ticket.
I need the exact overlapping time.
This is my Openticket table.
[Open_ID,SSTID,Createddatetime]
- 1,1,2020-04-27 06:40:32.337
- 2,1,2020-04-27 12:40:32.337
- 3,1,2020-04-27 14:40:32.337
- 4,1,2020-04-27 15:40:32.337
- 5,1,2020-04-27 18:40:32.337
This is my Close_ticket table.
[Close_id,open_id,SSTID,Createddatetime]
- 1,1,1,2020-04-27 20:40:32.337
- 2,2,1,2020-04-27 15:40:32.337
- 3,3,1,2020-04-27 16:40:32.337
- 4,4,1,2020-04-27 17:40:32.337
- 5,5,1,2020-04-27 21:40:32.337
You keep saying "the logic I've used so far is the one I mentioned" but at no point have you actually mentioned this logic in any useful form so that anyone can understand what it is you are doing: all you are doing is stating numbers with no indication on how you calculated these numbers.
Please provide a step by step guide to show how you calculated an overlap figure of 4 hours for the first 3 tickets.
For example, taking your data but moving the start/end times to the hour (rather than 40:32.337) for the sale of simplicity, we have this:
Possible overlap calculations:
2 overlaps 1 by 3 hours => overlap is 3
3 overlaps 1 by 3 hours => overlap is 3
You want to calculate overlap of both 2 & 3 compared to 1: 3 + 3 = 6
You only want the overlap when all 3 tickets overlap: 1
You don't want to double count any overlap: 2 overlaps 1 by 3 hours, 3 overlaps 1 by 3 hours, 2 & 3 overlap each other by 1 hour (double count) => 3 + 3 - 1 = 4
So which of these possible calculations are you using or are you using completely different logic and, if so, what it that logic?

Need help grouping a column that may or may not have the same value but have the same accounts

How do I output data stored in Table 1 so that each like account number has that also has the same CPT group's together but the ones that do not match fall to the bottom of the list?
I have one table: select * from CPTCounts and this is what is displays
Format (relevant fields only):
account OriginalCPT Count ModifiedCPT Count
11 0 71010 1
11 71010 1 0
2 0 71010 1
2 0 71020 9
2 0 73130 1
2 0 77800 1
2 71010 1 0
2 71020 8 0
2 73130 1 0
2 73610 1 0
2 G0202 4 0
31 99010 1 0
31 0 99010 4
31 0 99700 2
What I want the results to be grouped like is below... and display like this or similar.
Account OriginalCPT Count ModifiedCPT Count
11 71010 1 71010 1
2 71010 1 71010 1
2 71020 8 0
2 73130 1 0
2 73610 1 0
2 G0202 4 0
31 99010 1 99010 4
31 0 99700 2
I have one table with the values above;
Select * from #CPTCounts
The grouping I am looking for is the Original = Modified CPT and sometimes I will not have a value in one side or the other but most of the times I will have a match. I would like to place all of the unmatched ones at the bottom of the account.
any suggestions?
I was thinking of creating a second table and joining the two with the account but how do I return each value?
select cpt1.account, cpt1.originalCPT, cpt1.count, cpt2.modifiedcpt, cpt2.count
from #cptcounts cpt1
join #cptcounts cpt2 on cpt1.accont = cpt2.account
but am having trouble with that solution.
I'm not sure I have an exact solution, but perhaps some food for thought at least. The fact that you need either the "original" or the "modified" set of columns makes me think that you need a full outer join rather than a left join. You don't mention which database you are using. In MySql, for example, full joins can be emulated by means of a union of a left and a right join, as in the following:
select cpt1.account, cpt1.originalCPT, cpt1.countO, cpt2.modifiedcpt, cpt2.countM
from CPTCounts cpt1
left outer join CPTCounts cpt2
on cpt1.account = cpt2.account
and cpt1.originalCPT=cpt2.modifiedCPT
where cpt1.account is not null
and (cpt1.originalCPT is not null or cpt2.modifiedCPT is not null)
union
select cpt1.account, cpt1.originalCPT, cpt1.countO, cpt2.modifiedcpt, cpt2.countM
from CPTCounts cpt1
right outer join CPTCounts cpt2
on cpt1.account = cpt2.account
and cpt1.originalCPT=cpt2.modifiedCPT
where cpt2.account is not null
and (cpt1.originalCPT is not null or cpt2.modifiedCPT is not null)
order by originalCPT, modifiedCPT, account
The ordering brings the non-matching rows to the top, but that seemed a lesser problem than getting the matching to work.
(Your output data is a bit confusing, because the CPT 71020, for example, occurs in both original and modified columns, but you haven't shown it as one of the matching ones in your result set. I'm presuming this is because it is just an example... but if I'm wrong, then I am missing some part of your intention.)
You can play around in this SQL Fiddle.

access SQL count results using multiple sub queries against one table

I am using Access with a table having over 200k rows of data. I am looking for counts on a column which is broken down by job descriptions. For example, I want to return the total count (id) for a location where a person is status = "active" and position like "cook" [should equal 20] also another output where I get a count (id) for the same location where a person is status = "active" and position = "Lead Cook" [should equal 5]. So, one is a partial of the total population.
I have a few others to do just like this (# Bakers, # Lead Bakers...). How can I do this with one grand query/subquery or one query for each grouping.
My attempt is more like this:
SELECT
a.location,
Count(a.EMPLOYEE_NUMBER) AS [# Cook Total], --- should equal 20
(SELECT count(b.EMPLOYEE_ID) FROM Table_abc AS b where b.STATUS="Active Assignment" AND b.POSITION Like "*cook*" AND b.EMPLOYEE_ID=a.EMPLOYEE_ID) AS [# Lead Cook], --- should equal 5
FROM Table_abc AS a
ORDER BY a.location;
Results should be similar to:
Location Total Cooks Lead Cooks Total Bakers Lead Bakers
1 20 4 15 2
2 45 7 12 2
3 22 2 16 1
4 19 2 17 2
5 5 1 9 1
Try using conditional aggregation -- no need for sub queries.
Something like this should work (although I may not understand your desired results completely):
select location,
count(EMPLOYEE_NUMBER) as CookTotal,
sum(IIf(POSITION Like "*cook*",1,0)) as AllCooks,
sum(IIf(POSITION = "Lead Cook",1,0)) as LeadCooks
from Table_abc
where STATUS="Active Assignment"
group by location

T-SQL 2008 INSERT dummy row WHEN condition is met

**Schema & Dataset**
id version payment name
1 1 10 Rich
2 1 0 David
3 1 10 Marc
4 1 10 Jess
5 1 0 Steff
1 2 10 Rich
2 2 0 David
3 2 10 Marc
4 2 10 Jess
5 2 0 Steff
2 3 0 David
3 3 10 Marc
4 3 10 Jess
http://sqlfiddle.com/#!3/1c457/18 - Contains my schema and the dataset I'm working with.
Background
The data above is the final set after a stored proc has done it's processing so everything above is in one table and unfortunately I can't change it.
I need to identify in the dataset where a person has been deleted with a payment total greater than 0 in previous versions and insert a dummy row with a payment of 0. So in the above example, Rich has been deleted in version 3 with a payment total of 10 on previous versions. I need to first identify where this has happened in all instances and insert a dummy row with a 0 payment for that version. Steff has also been deleted on version 3 but she hasn't had a payment over 0 on previous versions so a dummy row is not needed for her.
Tried so far -
So I looked at pinal dave's example here and I can look back to the previous row which is great so it's a step in the right direction. I'm not sure however of how to go about achieving the above requirement. I've been toying with the idea of a case statement but I'm not certain that would be the best way to go about it. I'm really struggling with this one and would appreciate some advice on how to tackle it.
You can do this by generating all possible combinations of names and versions. Then filter out the ones you don't want according to the pay conditions:
select n.name, v.version, coalesce(de.payment, 0) as payment
from (select name, max(payment) as maxpay from dataextract group by name) n cross join
(select distinct version from dataextract) v left outer join
dataextract de
on de.name = n.name and de.version = v.version
where de.name is not null or n.maxpay > 0;
Here is a SQL Fiddle.

Error when COUNT after MAX?

I have a table Act in a medical database :
IDAct Historic IDPatient
1 2001-01-01 1
1 2001-01-02 1
2 2001-01-01 2
3 2001-01-03 1
I would like to compute the column IDActPerPatient:
IDAct Historic IDPatient IDActPerPatient
1 2001-01-02 1 1
2 2001-01-01 2 1
3 2001-01-03 1 2
The Act table contains Acts with the historic of every modification of an act. (the index is the pair (IDAct,Historic)).
So I'm interested in the last modified acts:
SELECT A.IDActe, MAX(Historic) AS Historic FROM Act A GROUP BY IDAct
Now, I'd like to number the Acts per patient. So I count the number of acts with an IDAct less or equal for one patient.
I have created a view LastAct with the previous request and I try this one :
SELECT DA1.*, COUNT(*) AS IDActPerPatient
FROM LastAct DA1
INNER JOIN LastAct DA2 ON DA1.IDPatient = DA2.IDPatient
AND DA2.IDActe >= DA1.IDAct
GROUP BY DA1.IDAct
...which does not work!
I get large numbers in IDActPerPatient when an act has several version in historic (for a patient who has 1 act in 3 versions I have 81).
Do you have an idea where the problem comes from ?
SELECT A.IDActe,
MAX(Historic) AS Historic,
(SELECT COUNT(DISTINCT IDAct) FROM ACT B WHERE A.IDPatient=B.IDPatient)
FROM Act A
GROUP BY IDAct
?
Thank you! I don't use select in the select enough but It's really helpful here!
here is the fixed request:
SELECT A.IDAct, A.IDPatient,
MAX(Historic) AS Historic,
(SELECT COUNT(DISTINCT IDAct) FROM Act B WHERE A.IDPatient=B.IDPatient
AND A.IDAct>=B.IDAct) AS IDActPerPatient
FROM Act A
GROUP BY IDAct