SQL Query to retrieve data joining same table - sql

I have a table and data like below.
ID is distinct for each record, recno is record number which goes multiple status changes as below table. I need to query recno which are in error status and never go to closed status. From below sample data I should get recno 3 as result since record 1 and 2 has error status but those have closed status.
**ID recno status**
1 1 Started
2 1 inProgress
3 1 released
4 1 error
5 1 closed
6 2 Started
7 2 inProgress
8 2 released
9 2 error
10 2 error
11 2 Closed
12 3 Started
13 3 inProgress
14 3 released
15 3 error

If you want the last status, you can do:
select t.*
from t
where t.id = (select max(t2.id) from t t2 where t2.recno = t.recno);
If you want the ones that are in error status:
select t.*
from t
where t.id = (select max(t2.id) from t t2 where t2.recno = t.recno) and
t.status = 'error';
Note: In most databases and even in some versions of Sybase, you can use row_number() for this query as well. However, not all versions of Sybase support window functions.

Related

Fetching data from DB and populate a partitioned List

I am confused about this both from front end point of view as well as querying the data from SQLite Database. If you have any idea how to solve either of these please do answer.
SQLite Database
I have a table likes this:
transactionId | productId | quantity
1 2 1
2 4 0
3 1 null
4 3 1
5 9 1
6 6 0
7 1 1
8 7 1
9 8 1
10 2 1
11 0 null
12 3 1
13 5 1
14 7 1
15 1 0
16 2 1
17 9 1
18 0 null
19 2 1
Now I want to display this data in groups of 5 units(i.e. groups till 5 units are completed) in list in my flutter app.
So 1st group will have 8 items,
2nd will have 6 items,
and 3rd group will have 5 items
(and is still incomplete since more items can be added till quantity for that group becomes 5)
Something like this:
Now my App can have multiple groups like this. Also, I don't think Grid view builder can work here since for each group I'll have to display some data for the group as well as accumulated data (which isn't shown in the picture)
Questions:
1) How to query data from SQFLite database?
2) How to display the queried data in my Flutter App front end?
Unfortunately, this type of problem requires a recursive CTE (or other iterative processing).
Assuming that transactionId is consecutive with no gaps:
with recursive cte as (
select transactionId, productId,
coalesce(quantity, 0) as quantity,
1 as bin
from t
where transactionId = 1
union all
select t.transactionId, t.productId,
(case when cte.quantity > 5
then 0 else cte.quantity
end) + coalesce(t.quantity, 0) as quantity,
(case when cte.quantity > 5 then 1 else 0 end) + cte.bin as bin
from cte join
t
on t.transactionId = cte.transactionId + 1
)
select *
from cte;
If transactionId has gaps or other issues, just use row_number() (in another CTE) to create an appropriate column for the where clauses.

Querying duplicates table into related sets

We have a process that creates a table of duplicate records based on some arbitrary rules (details not relevant).
Every record gets checked against all other records and if a suspected duplicate is found both it and the duplicate are stored in a dupes table to be manually reviewed.
This results in a table something like this:
dupId, originalId, duplicateId
1 1 2
2 1 3
3 1 4
4 2 3
5 2 4
6 3 4
7 5 6
8 5 7
9 6 7
10 8 9
You can see here record #1 has 3 other records it is similar to (#2,#3 and #4) and they are each similar to each other.
Record #5 has 2 duplicates (#6 and #7) and record #8 has only 1 (#9).
I want to query the duplicates into sets, so my results would look something like this:
setId recordId
1 1
1 2
1 3
1 4
2 5
2 6
2 7
3 8
3 9
But I am too old/slow/tired/rubbish and a bit out of my depth here.
Currently, when checking for duplicates if the record pairing is already in the table we don't insert it twice (i.e. you don't see both sides of the duplicate pairing) but can easily do so if it makes the querying simpler.
Any advice much appreciated!
Duplicates seems to be transitive, so you have all pairs. That is, the "original" id has the information you need.
But it is not included in the duplicates and you want that. So:
select dense_rank() over (order by originalid) as setid, duplicateid
from ((select originalid, duplicateid
from t
where not exists (select 1 from t t2 where t.originalid = t2.duplicateid)
) union all
(select distinct originalid, originalid
from t
where not exists (select 1 from t t2 where t.originalid = t2.duplicateid)
)
) i
order by setid;

Retrieve unique rows based on id

I have two tables:
Report
ReportId CreatedDate
1 2018-01-12
2 2018-02-12
3 2018-03-12
ReportSpecialty
SpecialtyId ReportId IsPrimarySpecialty
1 1 1
2 2 1
3 3 1
1 2 0
1 3 0
I am trying to write a query that will retrieve me the last 10 reports that were published. However, I need to get 1 report from each specialty. Assume there are 100 specialties, I can pass in as an argument any number of specialties, 10, 20, 5, 2, etc...
I'm trying to figure out a way where if I send it all specialties, it will get me the last 10 reports posted based on the last date created, but it won't give me 2 articles from same specialty. If I send it 10 specialties, then I will get 1 of each. If I send it 5, then I'll get 2 of each. If I send it 3 then I'll get 4 of 1 and 3 of other two.
I may need to write multiple queries for this, I'm trying to see if there is a way to do this on the SQL side of things? If there isn't, then how would I break down to multiple queries to get the result I want?
What I have tried is this, however I get multiple reports with same specialties:
SELECT TOP 10 r.ReportId, rs.SpecialtyId, r.CreatedDate
FROM Report r
INNER JOIN ReportSpecialty rs ON r.ReportId = rs.ReportId AND rs.IsPrimarySpecialty = 1
GROUP BY rs.SpecialtyId, r.AceReportid, r.CreatedDate
ORDER BY r.CreatedDate DESC
with cte as (
SELECT R.ReportId, R.CreatedDate, RS.SpecialtyId,
ROW_NUMBER() OVER (PARTITION BY RS.SpecialtyId
ORDER BY R.CreatedDate DESC) as rn
FROM Report R
JOIN ReportSpecialty RS
ON R.ReportId = RS.ReportId
AND RS.IsPrimarySpecialty = 1
WHERE RS.SpecialtyId IN ( .... ids ... )
)
SELECT TOP 10 *
FROM cte
ORDER BY rn, CreatedDate DESC
row_number will create a id for each speciality, so if you pass 3 speciality you will get something like this.
rn speciality_id
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3

Get The Latest Records from Table 2 with a twist

So I have 2 tables . MobileRequest and MobileRequestAnswers.
Format of tables like so :
Table 1 - Mobile Request
ID Job_Number MobileRequestID CreatedOn
1 12 23 1-March-2017
2 12 25 1-Dec-2017
3 13 57 1-Jan-2016
Table 2 - Mobile Request Answers
ID ResourceID MobileRequestID QuestionID Answer
1 10 23 1 Space R
2 10 23 2 Boston
3 10 23 4 Good
4 10 25 2 New York
5 10 25 1 Space D
6 10 25 5 Jimmy
7 12 57 3 Bobby
What I need to find is find the most recent MobileRequests ( Table 1) for a job number, that does not have question id 4 in the set of records from MobileRequestAnswers ( Table 2), as long as it is the most recent mobile request and has other records in Table for that mobile request id for other questions. The join between the tables is MobileRequestID.
Example 1
So for instance for Job Number 12 , I should receive no mobile request ID back as mobile request id 25 has a question id 4 in the 1st set of records returned in Table 2.
Example 2
For Job Number 13, I should get Mobile Request ID 57.
Tried a few combos of self joins but cant get the result I expect yet, so any steer would be appreciated.
Without knowing if there is a job table, I would start with something like the following to get only the jobs that have no question 4 associated to them in mobile_request_answers.
WITH
jobs_checked_question_4 AS
(
SELECT
mr.*,
MAX(
CASE WHEN mra.QuestionID = 4 THEN 1 ELSE 0 END
)
OVER (PARTITION BY mr.job_number) AS HasQuestionID4,
RANK() OVER (PARTITION BY mr.job_number
ORDER BY mr.CreatedOn ) AS RequestRank
FROM
mobile_request AS mr
LEFT JOIN
mobile_request_answer AS mra
ON mra.MobileRequestID = mr.MobileRequestID
)
SELECT
*
FROM
jobs_checked_question_4
WHERE
HasQuestionID4 = 0 -- The job never associates to a QuestionID 4
AND RequestRank = 1 -- The most recent Request for each Job
Will return all the answer records for the most recent request for each job, provided that the job has no request records that associated to an answer with QuestionID = 4
Can return multiple requests for the same job if those requests were created on the same date.

Select Max Access Query - row max for column with WHERE criteria

Microsoft Access 2010
I'm trying to get the Max visit number of a user within a sequence of visits less than or equal to 13 months apart.
So the last visit that was within a sequence of visits less than or equal to 13 months apart. I want to exclude those who only occasionally use it (ie. over 13 months apart)
I'm using this to run my query:
SELECT ID, AppointmentDate, Visit
FROM tblVisitQuestions t1
WHERE t1.Visit =
(SELECT Max(t2.Visit)
FROM tblVisitQuestions t2
WHERE t2.ID=t1.ID AND (DateDiff("m",[t1].[AppointmentDate],[t2].[AppointmentDate]) <= 13)
GROUP BY t2.ID)
Its working except that its returning multiple values for the same ID number.
Not sure if its an error within my data or my query.
Ex: example data in table
CR AppointmentDate Visit
1 15-Apr-05 0
1 15-Jul-05 1
1 16-May-06 2
1 06-Jun-06 3
1 19-Dec-06 4
1 11-Nov-11 5
1 31-Jan-12 6
2 08-Jun-04 0
2 17-Dec-04 1
2 05-Jul-05 2
2 06-Dec-05 3
2 06-Feb-09 4
2 19-Apr-11 5
what I would like after the query (not what I'm getting now)
CR AppointmentDate Visit
1 19-Dec-06 4
2 06-Dec-05 3
what I am actually getting:
CR AppointmentDate Visit
1 19-Dec-06 4
1 31-Jan-12 6
2 06-Feb-09 4
2 19-Apr-11 5
I need a way to select the min value of the max values I am getting
Any help would be greatly appreciated!
Thanks
For each visit, you can get the maximum visit number in the 13 months afterwards by doing:
SELECT ID, AppointmentDate, Visit,
(SELECT Max(t2.Visit)
FROM tblVisitQuestions as t2
WHERE t2.ID = t1.ID AND (DateDiff("m",[t1].[AppointmentDate],[t2].[AppointmentDate]) <= 13)
) as MaxVisit
FROM tblVisitQuestions as t1;
If you want this only where the visit number is one, then add a where clause:
WHERE t1.Visit = 1;