SQL Flag consecutive (follow) records - sql

I am relatively new to SQL and I tried to look for a similar question but I was not sure if the question related to my problem or that the answer might have been above skill level.
I think that the question is simple but I am not sure if the solution is simple.
I have the following sql table output
Room Name Time in Room Turnover Date
11 Mansson 740 NA 1/21/2017
11 Klein 841 NA 1/21/2017
11 Klein 1035 28 1/21/2017
I would like to write a query where I can flag fields where the following records are consecutive - Room, Name, Date.
This would flag the last 2 rows where Name is Klein.
Is there a way to do this, if yes can please guide me.

You can add a room/name/date flag using ANSI standard window functions:
select t.*,
(case when count(*) over (partition by room, name, date) > 1
then 1 else 0
end) as HasDuplicatesFlag
from t;

Related

Find out number of people who are at the office at 6 p.m

I have a simple query to which I forgot the solution, I remember there was a function to look for each possible value in a range, so I am asking this query here.
There is a table 'Time' with 2 columns checkInTime and CheckOutTime of the employees for one day in the office.
in the format: hour*100+minutes
For instance:
Check in
Check out
850
1758
902
1640
1330
1530
1630
2020
Find out the number of people which were in office at 6 pm (1800)
To this I came with this query (obviously its wrong since I dont know how to look for the value 1800 in the checkin-checkout range):
select sum(rn)
from Table
row_number() over() as rn
Where Checkout >= 1800
SELECT COUNT(*)
FROM table
WHERE 1800 BETWEEN CheckIn AND CheckOut)
That said this is incomplete without a full date to qualify that they were not in longer than a day.

Conditional Sum SQL

I am very new to SQL and have been presented with, what seems to me, a complex task. I have a table which is generating the number of various fruit purchased on a given day. Thus:
G. A G.B
2016-06-01 Banana 45 0
2016-06-01 Pear 158 0
2016-06-01 apple 0 23
.... dates continue
I need to develop some kind of conditional sum to count how many types of fruit are bought with a specific grade on a specific date. So in the above case on the given date (2016-06-01) there would be 203 Grade A (G.A) bits of fruit and 23 Grade B (G.B) pieces of fruit.
Naturally some kind of
Sum(case when date=date then Grade else 0 ).
But, I am really baffled here. Please, any help would be greatly appreciated!!!!
A simple group clause should do the job here (Note: untested code)
select date, sum(grade_a) as grade_a_sum, sum(grade_b) as grade_b_sum
from sales
group by date;
This will give the grades for every date. Individual dates can then be selected if necessary.
Won't simple group by do the work..
Select
date,
sum(GA) as GA,
sum(GB) as GB
from
Table
group by date

How can I return rows which match on some columns and fulfil a DateTime comparison between two other columns using SQL?

I have a table which contains rows for jobs, example below, where 01/01/1980 is used rather than null in the ClosedDate column for jobs which are not finished:
JobNumber JobCategory CustomerID CreatedDate ClosedDate
1 Small 1 01/01/2016 03/01/2016
2 Small 2 03/01/2016 07/01/2016
3 Large 2 06/01/2016 07/01/2016
4 Medium 1 08/01/2016 10/01/2016
5 Small 3 10/01/2016 01/01/1980
6 Medium 3 15/01/2016 01/01/1980
7 Large 2 16/01/2016 17/01/2016
8 Large 2 19/01/2016 20/01/2016
9 Small 1 19/01/2016 01/01/1980
10 Medium 2 19/01/2016 01/01/1980
I need to return a list of any jobs where the same customer has had a job of the same category created within 3 days of the previous job being closed.
So, I would want to return:
7 Large 2 16/01/2016 17/01/2016
8 Large 2 19/01/2016 20/01/2016
because Customer 2 had a Large job closed on 17/01/2016 and another Large job opened on 19/01/2016, which is within 3 days.
In order to do this, I assume I need to compare each record in the table with each subsequent record, looking for a match on JobCategory and comparing CreatedDate with ClosedDate between rows.
Can anyone advise my best option for this using SQL? I'm using SQL Server 2012.
The first thing that you should do is get rid of "magic dates" in your system. If the job hasn't been closed yet then the ClosedDate is not known. SQL has a value for exactly that - NULL. That prevents anyone in the future from having to know the magic date of 1/1/1980 or from that having to be hard-coded throughout your system.
Next, you don't have to compare each row with each one after it. Define what you're looking for and find matches that meet those qualifications. You didn't specify which type of SQL Server you're using (you should tag your question with Oracle or MySQL or SQL Server), so the below query is written for SQL Server. Your version might have different date functions.
SELECT
J1.JobNumber,
J1.JobCategory,
J1.CustomerID,
J1.CreatedDate,
J1.ClosedDate,
J2.JobNumber,
J2.CreatedDate,
J2.ClosedDate
FROM
Jobs J1
INNER JOIN Jobs J2 ON
J2.CustomerID = J1.CustomerID AND
J2.JobCategory = J1.JobCategory AND
DATEDIFF(DAY, J1.ClosedDate, J2.CreatedDate) BETWEEN 0 AND 3 AND
J2.JobNumber <> J1.JobNumber
This will return the jobs in a single row instead of two rows. If that's a problem then the query could be altered slightly to do so. This can also be done a little more easily with windowed functions, but again, since you didn't specify your SQL vendor I didn't want to use those.
Since you're using SQL Server, you should be able to use windowed functions like so:
;WITH CTE_JobsWithDates AS -- Probably a poor name for the CTE
(
SELECT
JobNumber,
JobCategory,
CustomerID,
CreatedDate,
ClosedDate,
LEAD(CreatedDate, 1) OVER (PARTITION BY JobCategory, CustomerID ORDER BY CreatedDate) AS NextCreatedDate,
LAG(ClosedDate, 1) OVER (PARTITION BY JobCategory, CustomerID ORDER BY CreatedDate) AS PreviousClosedDate
FROM
Jobs
)
SELECT
JobNumber,
JobCategory,
CustomerID,
CreatedDate,
ClosedDate
FROM
CTE_JobsWithDates
WHERE
DATEDIFF(DAY, ClosedDate, NextCreatedDate) BETWEEN 0 AND 3 OR
DATEDIFF(DAY, LastClosedDate, CreatedDate) BETWEEN 0 AND 3
That was off the cuff, so please test and let me know if anything isn't quite right.
Try:
SELECT a.*
FROM
Job AS a
JOIN
Job AS b ON
a.CustomerID = b.CustomerID AND a.JobCategory = b.JobCategory
WHERE
a.JobNumber != b.JobNumber
AND (
b.CreatedDate - a.ClosedDate BETWEEN 0 AND 3
OR
a.CreatedDate - b.ClosedDate BETWEEN 0 AND 3)

SQL Percentile function missing?

It is a mystery to me with this text book example. We have simply:
Transaction_ID (primary key), Client_ID, Transaction_Amount, Month
1 1 500 1
2 1 1000 1
3 1 10 2
4 2 11 2
5 3 300 2
6 3 10 2
... ... ... ...
I want to calculate in SQL the mean(Transaction_Amount), std(Transaction_Amount) and the some percentile(Transaction amount) grouped by Client_ID. But is seems, even given that percentile is a very similar calculation than the standard deviation, SQL cannot do it with a simple statement as:
SELECT
mean(Transaction_Amount),
std(Transaction_Amount),
percentile(Transaction_Amount)
FROM
myTable
GROUP BY
Client_ID, Month
Or can it?
It gets worse becuase I also need to Group By Month in addition to Client_ID.
Thanks a lot!
Sven
I'm sure Oracle can do the calculations you want. I just don't know what they are. You specify that you want something grouped by ClientId. Yet, your sample query has two keys in the GROUP BY.
Some functions that you want to look at are:
AVG()
STDDEV()
PERCENT_RANK()
Without sample data and desired results (or a very clear explanation of what you are trying to calculate), I can't put together a query.

Rank based on sequence of dates

I am having data as below
**Heading Date**
A 2009-02-01
B 2009-02-03
c 2009-02-05
d 2009-02-06
e 2009-02-08
I need rank as below
Heading Date Rank
A 2009-02-01 1
B 2009-02-03 2
c 2009-02-05 1
d 2009-02-06 2
e 2009-02-07 3
As I need rank based on date. If the date is continuous the rank should be 1, 2, 3 etc. If there is any break on dates I need to start over with 1, 2, ...
Can any one help me on this?
SELECT heading, thedate
,row_number() OVER (PARTITION BY grp ORDER BY thedate) AS rn
FROM (
SELECT *, thedate - (row_number() OVER (ORDER BY thedate))::int AS grp
FROM demo
) sub;
While you speak of "rank" you seem to want the result of the window function row_number().
Form groups of consecutive days (same date in grp) in subquery sub.
Number rows with another row_number() call, this time partitioned by grp.
One subquery is the bare minimum here, since window functions cannot be nested.
SQL Fiddle.
Note that I went with the second version of your contradictory sample data. And the result is as #mu suggested in his comment.
Also assuming that there are no duplicate dates. You'd have to aggregate first in this case.
Hi this is not correct answer, I am trying.. It is interesting..:) I am posting what I got so far: sqlfiddle
SELECT
rank() over (order by thedate asc) as rank,
heading, thedate
FROM
demo
Order by
rank asc;
Now I am trying to get the break in dates. I don't know how? But may be these links useful
SQL — computing end dates from a given start date with arbitrary
breaks
How to rank in postgres query
I will update if I got anything.
Edit:
I got this for mysql, I am posting this because it may helpful. Check Emulate Row_Number()
Here
Given a table with two columns i and j, generate a resultset that has
a derived sequential row_number column taking the values 1,2,3,... for
a defined ordering of j which resets to 1 when the value of i changes
Bangalore BLR - Bagmane Tech Park 2013-10-11 Data Centre 0
Bangalore BLR - Bagmane Tech Park 2013-10-11 BMS 0
Bangalore BLR - Bagmane Tech Park 2013-10-12 BMS 0
Bangalore BLR - Bagmane Tech Park 2013-10-15 BMS 3
I am having data lyk this..
If last column is zero the rank should be made based on all columns..If the date is continuous
like 2013-10-11 ,2013-10-12 rank should be 1,2...
If there is any break in date 2013-10-11 ,2013-10-12 and 2013-10-15 again the rank should start from 1 for 2013-10-15