Access SQL query with nulls and aggregate function - sql

Tried to come up with SQL query in MS Access, but null values and an aggregate function have me stumped. Any help appreciated.
Query to show records from TABLE1 where the EditDate (which may be null) is greater than the maximum LastImportDate from TABLE2.
TABLE1
Field Name - Data Type
ReportID - Number
EditDate - Date/Time
TABLE2
Field Name - Data Type
LastImportDate - Date/Time
Thank you.

SELECT *
FROM table1
WHERE editDate > (
SELECT max(lastImportDate)
FROM table2
)
not sure how exactly that translates to an access query, but that is the idea.
Additionally, if you could break out the max date as a separate variable, that will get you a bit better performance - something like:
DECLARE #maxDate DATETIME
SET #maxDate = (
SELECT max(lastImportDate)
FROM table2
)
SELECT *
FROM table1
WHERE editDate > #maxDate
Lastly, if you wanted to dates that have a null editDate, you can have the query interpret nulls as some arbitrary date like isNull(editDate, '1900-01-01') - this will make null editDates get interpreted as 1900 Jan 1

Related

Need help in sql Query.neo

In this table there are three colum and in need the value for of data which are lesser than code = 28,this is my query
SELECT value,code,date
FROM table
order by date,vchcode
but when i ad where clouse like
SELECT value,code,date
FROM table
where code < 28
order by date,vchcode
is only shows 2 row with code 26 and 27... i need 26,27 and 32.. and table colums are variable its not fix..
I think you wnat to take the date into account -- what you really want are all rows before the date of the row with code 28.
One method uses a subquery:
SELECT t.value, t.code, t.date
FROM table t
WHERE date < (SELECT date FROM table t2 WHERE t2.code = 28)
ORDER BY t.date, t.vchcode

Skip rows for specific time in SQL

Need a help.
I have two timestamp columns, so basically I want to get the max and min value with a thirD column showing as timedifference. I am skipping any 12.am time so used the syntax below. ANy help how to achieve the third column, timedifference.. It is in DB2.
SELECT EMPID,MIN(STARTDATETIME),MAX(ENDDATETIME)
FROM TABLE
WHERE DATE(STARTDATETIME)= '2012-05-15' AND HOUR(STARTDATETIME)<>0 AND HOUR(ENDDATETIME)<>0
GROUP BY EMPID
You can use the results from that in an inner select, and use those values to define the TimeDifference column. My knowledge of DB2 is very limited, so I'm making some assumptions, but this should give you an idea. I'll update the answer if something is drastically incorrect.
Select EmpId,
MinStartDate,
MaxEndDate,
MaxEndDate - MinStartDate As TimeDifference
From
(
Select EMPID,
MIN(STARTDATETIME) As MinStartDate,
MAX(ENDDATETIME) As MaxEndDate
From Table
Where DATE(STARTDATETIME) = '2012-05-15'
And HOUR(STARTDATETIME) <> 0
And HOUR(ENDDATETIME) <> 0
Group By EMPID
) A

Sql Condition Operator in Sql query

Please Correct my query to Select data.
If there is an entry in LeaveApply Table having given date betwwn a from date and to date in the table, i should get the pK of table else zero.
please help
Select A,
B,
ISNULL((select LeaveApply_Id from Tbl_Stud_Leave_Apply where Candidate_Id=120
and ('01/13/2014 12:00:00 AM' between Stud_LeaveFromDate and Stud_LeaveToDate)),0) As Leave from TableA where Condition.
You have to apply the isnull to the column, not to the whole query.
Try the below
select ISNULL(LeaveApply_Id,0) AS ID from Tbl_Stud_Leave_Apply
where Candidate_Id= #Candidate and (#date between Stud_LeaveFromDate and Stud_LeaveToDate)
In the above #Candidate and #date are dynamically passed to query.
Note that if you do the lookup across a lot of results, you should consider a set-based approach to the lookup, e.g.
SELECT
c.*,
ISNULL(l.LeaveApply_Id, 0) AS IsLeave
FROM
Candidates c
LEFT OUTER JOIN Tbl_Stud_Leave_Apply l
on l.Candidate_Id=c.ID AND #Date between Stud_LeaveFromDate and Stud_LeaveToDate;

Creating new date field dynamically from next row

I have a table of data. I have a field which shows date. I had set this column as Start Date. I want to create an additional column as End Date, where the End Date will be the Start Date of the next row. Can you give me a query of creating the End Date by taking the data of the Start Date in next row ?
First of all, you have to come up with a definition of "order", since rows in a table are stored without any order.
When you know what your order is, you can create a stored procedure that goes:
insert into the_table (new_id, start_date) values (#id, #start_date);
update the_table
set end_date = #start_date
where id = <the id determined by your sorting rule>;
I'm assuming that you currently have rows with values such as
StartDate
---------
1 Jan 1990
2 June 1998
4 September 2006
And you want to change to
StartDate EndDate
--------- ------------
1 Jan 1990 2 June 1998
2 June 1998 4 September 2006
4 September 2006 NULL
Quite apart from the redundancy and maintenance issue that reminds me of this question where such a setup with correlated columns actually caused the original poster problems when querying data. (I prefer Unreason's answer to my own on that question!)
Why do you need to add the EndDate column? It will probably be possible to come up with a query that works without it.
Edit After much faffing about with row_number() I actually couldn't find a query with a better plan than this. (Assumes index on StartDate)
SELECT
id,
StartDate,
(SELECT MIN(StartDate)
FROM testTable t2
WHERE t2.StartDate > t1.StartDate) AS EndDate
FROM testTable t1
Assuming you already have your columns and that you have an Auto-Incrementing Primary Key:
Update T1
Set T1.EndDate = T2.StartDate
From [Table] T1
Inner Join [Table] T2 on T1.Id = T2.Id - 1
Depends on what you mean by "next" row.
Can you provide sample dataset, and specify how you determine what order the rows go in?
EDIT
Your record order really does matter -- you're going to have to determine what that is. For now, I'm working off of the assumption that ordering it by start_date is acceptable.
--GET the first relevant start date
declare #start datetime
set #start = select MIN(start_date) from table
declare #end datetime
set #end = #start
WHILE #end is not null
--GET the next relevant end date
SET #end = select MIN(start_date) from table where start_date > #start
--Update the table with the end date
UPDATE table
SET end_date = #end
WHERE start_date = #start
--GET the next relevant start date
SET #start = #end
END
What about last row? The endDate will be blank for that?
I'm answering this question because it is being referenced somewhere else.
Depending on the id having no holes is dangerous. identity columns can have gaps which the currently accepted answer does not take into account.
In SQL Server 2012+, the answer is simply lag(). In earlier versions, you can use cross apply:
Update T1
Set T1.EndDate = T2.StartDate
From [Table] T1 cross apply
(select top 1 t2.*
from [Table] T2
where t2.StartDate > t1.Startdate
order by t2.StartDate asc
) t2;
With an index on table(StartDate), this might even have reasonable performance.

update a field based on subtotal from another table

I'm using oracle(10).
I've got two tables as follows:
Table1 (uniq rows):
ID AMOUNT DATE
Table2:
ID AMOUNT1 AMOUNT2 ...AMOUNTN DATE
Table2 is connected many to one to Table1 connected via ID.
What I need is update-ing Table1.DATE with: the last (earliest) date from Table2 where Table1.AMOUNT - SUM(Table2.AMOUNT1) <= 0, when reading table 2 backwards by the Table2.DATE field.
Is there a simple way to do it?
Thanks in advance!
UPDATE: as I see from your answers I had misspecified the question a bit. So here goes a detailed example:
Table1 has:
ID: 1 AMOUNT:100 DATE:NULL
Table2 has (for ID: 1 so ID is not listed in here):
AMOUNT1 DATE
50 20080131
30 20080121
25 20080111
20 20080101
So in this case I need 20080111 as the DATE in Table1 as 50+30+25 => 100.
Based on your revised question, this is a case for using analytic functions.
Assuming you meant >=100 rather than <= 100 as your example implies, and renaming columns DATE to THEDATE since DATE is a reserved word in Oracle:
update table1 set thedate=
( select max(thedate) from
( select id, thedate,
sum(amount1) over (partition by id order by thedate desc) cumsum
from table2
) v
where v.cumsum >= 100
and v.id = table1.id
)
If the 100 means the current value of table1 then change that line to:
where v.cumsum >= table1.amount
First off - your database layout feels severely wrong, but I guess you can't / don't want to change it. Table1 should probably be a view, and Table2 does not make the impression of proper normalization. Something like (ID, AMOUNT_TYPE, AMOUNT_VALUE, DATE) would make much more sense to me.
But to solve your problem (this is T-SQL "UPDATE FROM" syntax, but I think Oracle knows it):
UPDATE
Table1
SET
Date = Table2Aggregate.MinDate
FROM
Table1
INNER JOIN (
SELECT Id, SUM(Amount1) SumAmount1, MIN(Date) MinDate
FROM Table2
GROUP BY Id
) AS Table2Aggregate ON Table1.Id = Table2Aggregate.ID
WHERE
Table1.Amount - Table2Aggregate.SumAmount1 <= 0