I have a table that has like a list of codes and the start and end date that the code was active. I want to select the most recent active codes. Which is simple enough but the part I'm getting stuck with is that you can have the same code with overlapping dates which means both are active and I'd need to select all these records. Or you can have the same codes but the dates follow on which means the previous one is no longer active and I want to ignore this.
See example of table below:
In the table below I'd essentially need to say okay this table if you have two of the same codes but the dates follow on then take most recent, if the dates overlap then select...
ID | Code | Start Date | End Date | I need to select
01 | A110 | 15/01/21 | NULL | select
02 | A110 | 14/05/19 | NULL | select
03 | A110 | 10/10/18 | 13/05/19 | Ignore
03 | B200 | 15/01/21 | NULL | select
04 | B200 | 10/12/20 | 14/01/21 | Ignore
05 | C600 | 15/01/21 | NULL | Select
to me it looks like
SELECT *
FROM TABLE
WHERE END_DATE IS NULL
but maybe i got the question wrong, it really isnt clear at the moment
Related
I have a table where the date parts are in separate fields and I am struggling to put a filter on it (pulling all the data is so much that it basically times out).
How can I write a sql query to pull the data for only the past 7 days?
| eventinfo | entity | year | month | day |
|------------|-------------------------|------|-------|-----|
| source=abc | abc=030,abd=203219,.... | 2022 | 08 | 07 |
| source=abc | abc=030,abd=203219,.... | 2022 | 08 | 05 |
| source=abc | abc=030,abd=203219,.... | 2022 | 07 | 33 |
Many thanks in advance.
You can use concatenation on your columns, convert them to date and then apply the filter.
-- Oracle database
select *
from event
where to_date( year||'-'||month||'-'||day,'YYYY-MM-DD') >= trunc(sysdate) - 7;
I'm sorry if my question doesn't make sense. I'm not sure how to word it. I just started self-studying SQL and there's something I want to do but I'm not sure how to do it. I'm hoping someone could help me out.
I have two tables where Table 1 is a list of students and Table 2 is a list of lab partners. Table 2 has students listed with their id numbers instead of names. The two tables can be joined together by student_id = student1_id (or student2_id).
Table 1
| student_id | student_name |
|------------|--------------|
| 01 | Alex |
| 02 | Ben |
| 03 | Chris |
| 04 | Dave |
Table 2
| group_number | student1_id | student2_id |
|--------------|-------------|-------------|
| 1 | 01 | 02 |
| 2 | 03 | 04 |
What would my select query look like if I wanted lab partners to show as names instead of id numbers? (See desired result below.)
Query result:
| group_number | (student_name of student1_id) | (student_name of student2_id) |
|--------------|-------------------------------|-------------------------------|
| 1 | Alex | Ben |
| 2 | Chris | Dave |
I'm actually stumped. I'm hoping someone could send me in the right direction. I would greatly appreciate the help!
You would join on the id columns with the Table1(that holds the name of students) twice-> one for student_1's name and one for student_2's name
select t2.group_number
,t11.student_name as student_name_1
,t12.student_name as student_name_2
from Table2 t2
join Table1 t11
on t2.student1_id=t11.student_id
join Table1 t12
on t2.student2_id=t12.student_id
To all the Oracle SQL pros, please, I'm trying to use a pivot to convert multiple rows into a single column. I tried looking through past posting but could not find anything related to what I want to do, or maybe I just don't know how to search for it properly. I want to take the rows HAND, PECO, CHEP and make that into 1 column called EXTRA, while leaving STORAGE and RENEWAL as their own separate columns. I'm stumped, any help would be greatly appreciated. Thanks in advance!
My current sql is,
select * from (
select company, customer, rev_code, sum(rev_amt) amt
from revenue_anal
where company='01'
and rev_date between to_date('20\01\01','YY\MM\DD') and sysdate
group by company, customer, rev_code
order by 2,1 )
pivot (sum(amt) for rev_code in ('HAND', 'PECO', 'CHEP', 'STORAGE', 'RENEWAL'))
Query,
COMPANY | CUSTOMER | REV_CODE | REV_AMT
---------------------------------------------------
01 | 101962 | HAND | 253.377
01 | 101962 | PECO | 60
01 | 101962 | CHEP | 1632
01 | 101962 | STORAGE | 2700
01 | 101962 | RENEWAL | 60
---------------------------------------------------
Output with my current query,
COMPANY | CUSTOMER | HAND | PECO | CHEP | STORAGE | RENEWAL
--------------------------------------------------------------------------
01 | 101962 | 253.377 | 60 | 1632 | 2700 | 60
Trying to get the output to show as
COMPANY | CUSTOMER | EXTRA | STORAGE | RENEWAL
------------------------------------------------------------------
01 | 101962 | 1945.377 | 2700 | 60
Thank you for taking the time to assist.
Instead of select * from ( at the very beginning of your query, write
select company, customer, hand + peco + chep as extra, storage, renewal
from (
.........
If you expect that any of HAND, PECO or CHEP may be NULL, wrap each of them individually within NVL(...., 0) (if, in fact, NULL is to be interpreted as zero; otherwise, leave as is, and the result will be NULL if at least one of the terms is NULL).
I have a table in Access that has a record of test results for each person for each day. Some people may have taken more than one test on the same day. I have shown a simplified version of this table below:
| ID | testDate | Person | Pass? | ConsecFailDays |
----------------------------------------------------------
| 01 | 01/08/18 | John | Fail | |
| 02 | 01/08/18 | John | Pass | |
| 03 | 03/08/18 | John | Fail | |
| 04 | 01/08/18 | Mark | Fail | |
| 05 | 02/08/18 | Mark | Pass | |
I have tried to write an SQL UPDATE query that will update the last column with the number of consecutive days that that person has failed at least one test (not necessarily consecutive calender days, just the days that they actually did a test). The final result should look like this...
| ID | testDate | Person | Pass? | ConsecFailDays |
----------------------------------------------------------
| 01 | 01/08/18 | John | Fail | 1 |
| 02 | 01/08/18 | John | Pass | 1 |
| 03 | 03/08/18 | John | Fail | 2 |
| 04 | 01/08/18 | Mark | Fail | 1 |
| 05 | 02/08/18 | Mark | Pass | 0 |
I was really struggling to get this to work and in the end I resorted to using VBA to create a recordset of each unique person and then loop through each day for that person to check if they had a fail on that day. My dataset is quite large and it is taking hours to run.
I expect that a query that operates on the entire set of data would be much quicker. Does anyone know if there is an SQL solution to this after all?
You need several subqueries to get the last date with a passed test and no fail, then count the days between this date and testDate:
SELECT t1.ID
,t1.testDate
,t1.Person
,t1.[Pass?]
,(
SELECT count(testDate)
FROM (
SELECT DISTINCT testDate
,Person
,[Pass?]
FROM yourTable
) AS t2
WHERE t2.[Pass?] = false
AND t2.Person = t1.Person
AND t2.testDate >= Nz((
SELECT max(t3.testDate)
FROM (
SELECT t4.testDate
,t4.Person
FROM yourTable AS t4
WHERE (
((t4.[Pass?]) = True)
AND (
(
(
SELECT count(*) AS failed
FROM yourTable AS t5
WHERE t5.testDate = t4.testDate
AND t5.Person = t4.Person
AND t5.[Pass?] = false
)
) = 0
)
)
) AS t3
WHERE t1.Person = t3.Person
AND t3.testDate <= [t1].[testDate]
GROUP BY Person
))
AND t2.testDate <= t1.testDate
) AS ConsecFailDays
FROM yourTable AS t1;
Where t2 counts the distinct days (you can drop DISTINCT if just one fail per day is posible to speed up).
t3 are the days with passed tests and no fail.
t4 are the days with passed tests (and maybe failed tests).
t5 counts the failed tests on a day with a passed test.
As you wanted an Update-Query you can use:
UPDATE yourTable SET ConsecFailDays = DLookUp("ConsecFailDays","newQuery","ID = " & yourTable.ID)
but you should try the Select-Query with indices first. If performance is too poor you can use the update, but you have to run it every time your data changes.
Suggestions:
Don't use specialchars like ? in Pass? for column or table names to avoid being forced to use square brackets.
Person should be a foreign-key to table persons as persons can have equal names (e.g John Smith).
[Pass?] should be boolean (true/false). If you want to stay on string you have to replace [Pass?] = false with [Pass?] = 'Fail' and [Pass?] = true with
[Pass?] = 'Pass'
there should be an index for testDate, Person and a combined index for testDate, Person to increase query performance.
I have data on approx 1000 individuals, where each individual can have multiple rows, with multiple dates and where the columns indicate the program admitted to and a code number.
I need each row to contain a distinct date, so I need to delete the rows of duplicate dates from my table. Where there are multiple rows with the same date, I need to keep the row that has the lowest code number. In the case of more than one row having both the same date and the same lowest code, then I need to keep the row that also has been in program (prog) B. For example;
| ID | DATE | CODE | PROG|
--------------------------------
| 1 | 1996-08-16 | 24 | A |
| 1 | 1997-06-02 | 123 | A |
| 1 | 1997-06-02 | 123 | B |
| 1 | 1997-06-02 | 211 | B |
| 1 | 1997-08-19 | 67 | A |
| 1 | 1997-08-19 | 23 | A |
So my desired output would look like this;
| ID | DATE | CODE | PROG|
--------------------------------
| 1 | 1996-08-16 | 24 | A |
| 1 | 1997-06-02 | 123 | B |
| 1 | 1997-08-19 | 23 | A |
I'm struggling to come up with a solution to this, so any help greatly appreciated!
Microsoft SQL Server 2012 (X64)
The following works with your test data
SELECT ID, date, MIN(code), MAX(prog) FROM table
GROUP BY date
You can then use the results of this query to create a new table or populate a new table. Or to delete all records not returned by this query.
SQLFiddle http://sqlfiddle.com/#!9/0ebb5/5
You can use min() function: (See the details here)
select ID, DATE, min(CODE), max(PROG)
from table
group by DATE
I assume that your table has a valid primary key. However i would recommend you to take IDas Primary key. Hope this would help you.