SQL Server Amount "Open" At Each Month End - sql-server

I need to create a query that will sum the Amount of Open Accounts Receivable for each month.
Each record in my table has Amount,Posting Date, and Closed at Date. So for example, one record might be: Amount : 5000, Posting Date : 1/1/15, Closed at Date : 3/5/15. So for this record, the 5000 would need to be added to my January Open AR calculation because it is open as of 1/31/15, added to my February Open AR calculation because it is open as of 2/28/15, but excluded from my March Open AR calculation because it is closed as of 3/31/15.
I have managed to create a query that will work for an individual month, given a single inputted month-end date, i.e. 1/31/15 or 2/28/15, etc..., which goes into the WHERE clause.
SELECT SUM(Amount), threemonthavg, SUM(Amount)/threemonthavg AS DSO
FROM tbl1
WHERE PostDate <= #enddate AND ClosedDate > #enddate
Am I on the right track to expand this out to include each month in one query or would I be better off taking what I have, and creating a stored procedure to run this query for each month and union the results together?

Related

Creating Attendance Report with SSRS

I am trying to create a Attendance result set in SQL Server for using it in a SSRS report. The Employee Attendance table is as below:
EmpId
ADate
In
Out
1
2023-01-01
8:00
15:00
I need to calculate the Total working days for all months in a year and display the number of working days per employee. Report format should be as follows:
Saturday and Sunday being weekend, I can able to get the no of working days monthly.
Another table tbl_Holiday has entries for holidays Fromdate and ToDate. I need to consider that also when calculating working days. Several number of results i got from the internet for calculating this. But when creating a view using this data , it has to calculate workdays for each employee row
SELECT
EmpName, EmpId,
(SELECT COUNT(*) FROM tbl_EmpAttendance
WHERE EmpRecId = A.RecId
GROUP BY MONTH(Adate), YEAR(Adate)) AS WorkedDays,
dbo.fn_GetWorkDays(DATEFROMPARTS(YEAR(ADate), MONTH(ADate), 1), EOMONTH(ADate)) AS workingDays
FROM
tbl_Employee A
LEFT JOIN
tbl_EmpAttendance B ON A.RecId = B.EmpRecId
fn_GetWorkDays - calculates the working days for month.
I need to get number of holidays from tbl_holiday too, I understand that this query is becoming more complex than I thought. There must be simpler way to achieve this, can anyone please help?
I tried to get the result in one single view, for using that as SSRS report dataset

how to skip a day to previous in sql database if that day produce no files

i need to print the files From the current day plus from the day before...but if the day before is sunday then i want to print the files from saturday
i have a database containing a files of a month..each day produces some files but sunday is a holiday and at that day no files are generated.now i have done the query to pick the files in such a way that giving current date will results the files of that day and previous day. But the problem is on monday when i give the current date it produces files of monday and sunday... i dont want to print files of sunday as it is null,instead of that when am giving the current date if its is monday i should get the files of saturday instead of monday.
this is the code am using now
select files from table1 where [date]>=DATEADD(DAY,DATEDIFF(DAY,0,GETDATE()-1),0) ";
except for sundays i have entered the files for each day
insert into dbtable(date,files) values('date value',' filename');
Assuming your are using SQL Server (and not MySQL), you can use a CROSS APPLY to get data for the last two [dates] with files:
SELECT *
FROM dbo.table1 o
CROSS APPLY ( SELECT TOP 2 [date]
FROM dbo.table1 i
GROUP BY [date]
WHERE [date]>=DATEADD(DAY,DATEDIFF(DAY,0,GETDATE()-5),0)
ORDER BY [date] DESC
) det
WHERE det.[date] = o.[date]
Look for both dates, the current and the one before. From these records take the newer one.
select files
from table1
where date =
(
select max(date)
from table1
where date in (getdate(), getdate() - interval 1 day)
);
(Updated regarding Code-Monk's commment. Thanks.)
This is standard SQL except for the date manipulation which is MySQL specific. If you were mistaken with the DBMS tagged, then replace the part where a day is subtracted from current day with what's appropriate for your DBMS.)
UPDATE: You want to select from two days, the currect day and the last date before. As there should be no future records, this always means the two maximum dates in your table.
The slightly altered query using ORDER BY and LIMIT:
select files
from table1
where date in
(
select date
from table1
order by date desc limit 2
);
Try MySQL function DAYNAME(date1) to check for day is sunday,If so then get difference of two days instead of one.
mysql> SELECT DAYNAME(GETDATE());
+-----------------------+
| DAYNAME('2008-05-15') |
+-----------------------+
| Thursday |
+-----------------------+
1 row in set (0.01 sec)
If you are using SQL server,you can try datename function to get the day name:
datename(dw,getdate())
Try this for SQL Server:
SELECT files from table1
where [date]>=DATEADD(DAY,case when datename(dw,(GETDATE()-1))='SUNDAY' THEN -2 ELSE -1 END,getdate());
For MySQL Server Try:
SELECT files from table1
where `date`>=DATE_SUB(current_Date,interval (case when DAYNAME(date_sub(current_date,interval 1 day))='SUNDAY' THEN 2 ELSE 1 END) day);
Hope this works, because I don't have mysql here to test (only SQL Server):
SELECT files FROM table1
WHERE CAST([date] AS DATE) IN (CURDATE() - CASE DATEPART(dw,GETDATE()) WHEN 2 /* Monday */ THEN 2 ELSE 1 END, CURDATE())
The idea is to test if the date (as date only, no time part) falls in a specific list of dates, being today and yesterday or Saturday.

SQL Server Stored Procedure get nearest available date to parameter

I have a table of database size information. The data is collected daily. However, some days are missed due to various reasons. Additionally we have databases which come and go over or the size does not get recorded for several databases for a day or two. This all leads to very inconsistent data collection regarding dates. I want to construct a SQL procedure which will generate a percentage of change between any two dates (1 week, monthly, quarterly, etc.) for ALL databases The problem is what to do if a chosen date is missing (no rows for that date or no row for one or more databases for that date). What I want to be able to do is get the nearest available date for each database for the two dates (begin and end).
For instance, if database Mydb has these recording dates:
2015-05-03
2015-05-04
2015-05-05
2015-05-08
2015-05-09
2015-05-10
2015-05-11
2015-05-12
2015-05-14
and I want to compare 2015-05-06 with 2015-05-14
The 2015-05-07 date is missing so I would want to use the next available date which is 2015-05-08. Keep in mind, MyOtherDB may only be missing the 2015-05-06 date but have available the 2015-05-07 date. So, for MyOtherDb I would be using 2015-05-07 for my comparison.
Is there a way to proceduralize this with SQL WITHOUT using a CURSOR?
You're thinking too much into this, simple do a "BETWEEN" function in your where clause that takes the two parameters.
In your example, if you perform the query:
SELECT * FROM DATABASE_AUDIT WHERE DATE BETWEEN param1 /*2015-05-06*/ and param2 /*2015-05-14*/
It will give you the desired results.
select (b.dbsize - a.dbsize ) / a.dbsize *100 dbSizecChangePercent from
( select top 1 * from dbAudit where auditDate = (select min(auditDate) from dbAudit where auditDate between '01/01/2015' and '01/07/2015')) a
cross join
(select top 1 * from dbAudit where auditDate = (select max(auditDate) from dbAudit where auditDate between '01/01/2015' and '01/07/2015')) b
The top 1 can be replaced by a group by. This was assuming only 1 db aduit per day

Delete records based on dates

I have a database "DB" and I want to delete records from table "MyRecords" which are of future ("RecordDates" which are more than today just to avoid date change on system) and less than x no. of days from today.
That "x" may vary. Moreover, I want to execute same type of command with month and year also.
I am using SQL Server and C#.
To delete records which are in the future and less than n days in the future you could use T-SQL such as this:
DELETE FROM DB.table WHERE
(date > GETDATE() AND date < DATEADD(day, 5, GETDATE()));
In this case n is 5.
You can see all the arguments to DATEADD() at DATEADD (Transact-SQL)
This query will delete all records that are later than today's date, but less than 30 days in the future. You could replace "30" with a variable so you could determine how many days in the future to delete.
DELETE FROM Table
WHERE
TABDate > GETDATE() and TABDate < DATEADD(day, 30, GETDATE())
UPDATE
To delete all records less than 30 days in the past, you would change the query to look like this:
DELETE FROM Table
WHERE
TABDate > DATEADD(day, -30, GETDATE()) AND TABDate < GETDATE()
Also note that all these examples are calling GETDATE() which also has a time component as well as a date, so care must be taken in that anytime you see a statement like < GETDATE() you are not just deleting records with a date before, say, 2011-09-29, you are deleting all records with a date before '2011-09-29 17:30'. So be aware of that if you table dates contain times as well.
You can use the query DELETE FROM DB.table WHERE date > now() or WHERE date > unix_timestamp(), depending on how you are storing your dates. (i.e. date-time vs. timestamp).

SQL Server Retrieving Recurring Appointments By Date

I'm working on a system to store appointments and recurring appointments. My schema looks like this
Appointment
-----------
ID
Start
End
Title
RecurringType
RecurringEnd
RecurringTypes
---------------
Id
Name
I've keeped the Recurring Types simple and only support
Week Days,
Weekly,
4 Weekly,
52 Weekly
If RecurringType is null then that appointment does not recur, RecurringEnd is also nullable and if its null but RecurringType is a value then it will recur indefinatly. I'm trying to write a stored procedure to return all appointments and their dates for a given date range.
I've got the stored procedure working for non recurring meetings but am struggling to work out the best way to return the recurrences this is what I have so far
ALTER PROCEDURE GetAppointments
(
#StartDate DATETIME,
#EndDate DATETIME
)
AS
SELECT
appointment.id,
appointment.title,
appointment.recurringType,
appointment.recurringEnd,
appointment.start,
appointment.[end]
FROM
mrm_booking
WHERE
(
Start >= #StartDate AND
[End] <= #EndDate
)
I now need to add in the where clauses to also pick up the recurrences and alter what is returned in the select to return the Start and End Dates for normal meetings and the calculated start/end dates for the recurrences.
Any pointers on the best way to handle this would be great. I'm using SQL Server 2005
you need to store the recurring dates as each individual row in the schedule. that is, you need to expand the recurring dates on the initial save. Without doing this it is impossible to (or extremely difficult) to expand them on the fly when you need to see them, check for conflicts, etc. this will make all appointments work the same, since they will all actually have a row in the table to load, etc. I would suggest that when a user specifies their recurring date, you make them pick an actual number of recurring occurrences. When you go to save that recurring appointment, expand them all out as individual rows in the table. You could use a FK to a parent appointment row and link them like a linked list:
Appointment
-----------
ID
Start
End
Title
RecurringParentID FK to ID
sample data:
ID .... RecurringParentID
1 .... null
2 .... 1
3 .... 2
4 .... 3
5 .... 4
if in the middle of the recurring appointments schedule run, say ID=3, they decide to cancel them, you can follow the chain and delete the remaining ID=3,4,5.
as for expanding the dates, you could use a CTE, numbers table, while loop, etc. if you need help doing that, just ask. the key is to save them as regular rows in the table so you don't need to expand them on the fly every time you need to display or evaluate them.
I ended up doing this by creating a temp table of everyday between the start and end date along with their respective day of the week. I limited the recurrence intervals to weekdays and a set amount of weeks and added where clauses like this
--Check Week Days Reoccurrence
(
mrm_booking.repeat_type_id = 1 AND
#ValidWeeklyDayOfWeeks.dow IN (1,2,3,4,5)
) OR
--Check Weekly Reoccurrence
(
mrm_booking.repeat_type_id = 2 AND
DATEPART(WEEKDAY, mrm_booking.start_date) = #ValidWeeklyDayOfWeeks.dow
) OR
--Check 4 Weekly Reoccurences
(
mrm_booking.repeat_type_id = 3 AND
DATEDIFF(d,#ValidWeeklyDayOfWeeks.[Date],mrm_booking.start_date) % (7*4) = 0
) OR
--Check 52 Weekly Reoccurences
(
mrm_booking.repeat_type_id = 4 AND
DATEDIFF(d,#ValidWeeklyDayOfWeeks.[Date],mrm_booking.start_date) % (7*52) = 0
)
In case your interested I built up a table of the days between the start and end date using this
INSERT INTO #ValidWeeklyDayOfWeeks
--Get Valid Reoccurence Dates For Week Day Reoccurences
SELECT
DATEADD(d, offset - 1, #StartDate) AS [Date],
DATEPART(WEEKDAY,DATEADD(d, offset - 1, #StartDate)) AS Dow
FROM
(
SELECT ROW_NUMBER() OVER(ORDER BY s1.id) AS offset
FROM syscolumns s1, syscolumns s2
) a WHERE offset <= DATEDIFF(d, #StartDate, DATEADD(d,1,#EndDate))
Its not very elegant and probably very specific to my needs but it does the job I needed it to do.

Resources