compute total days work using query from vb6 to msaccess - sql

I am making a payroll system using vb6 with ms access as database. I have 3 tables in ms access namely:
tblemployee, tblattendance, tblpayroll
I want to get the payroll of all employees for the month of ex april, year 2013. All these datas will be from tblattendance.
Ex. (Some fields are hidden)
tblattendance:
Empid Day Month Year totalhourworkfor1day
1 1 april 2013 8
2 1 april 2013 5
1 2 april 2013 8
2 2 april 2013 5
tblpayroll:
empid month year Totalhoursworkfor1month
1 april 2013 16
2 april 2013 10
After querying for the month of april year 2013, all the totalhourworkfor1day for 1 employee will be added and the result will save in to Totalhoursworkfor1month.
How to do this? Considering that from my vb6, I only need to select the month and year to generate the payroll and after it will display to the listview
Tried code:
insert into tblpayroll(empid,month,year,hourswork)
select id,month, year, sum(hourswork) from tblattendance where empid=id group by empid;

Does this help?
The dates are just one field. I have used the MinOfWorkDay so as to avoid complications with months ending on 28,29,30,31. But this can be worked around if you want to have "month ending". In any event you could format results to simply show the month/year.
It could further enhanced by the HAVING clause defaulting to the month just ended, or using "from" and "to" dates entered on a form.
INSERT INTO tblPayroll ( Empid, HoursWorked, MonthEnd )
SELECT tblWork.Empid, Sum(tblWork.WorkHours) AS SumOfWorkHours, Min(tblWork.Workday) AS MinOfWorkday
FROM tblWork
GROUP BY tblWork.Empid
HAVING (((Min(tblWork.Workday)) Between #4/1/2013# And #4/30/2013#));
I'd be pleased to give more help if you come back with more questions.
15 Apr: I boobed! I assumed you would be processing your data in MS Access. I don't know vb6 so can't help any more. Could your whole project be done in access?

Related

Add results to a row regarding the last 12 months rows- SQL Server

At my last meeting someone asked me if it was possible to hide people who where ill since a year from a dashboard. So I'm searching for the best way to actually KNOW who has been ill for 12 months.
I am working with a table with the number of days you've been absent for every kind of absence you could have, the number of days you should have been working that month, with a row per person, department and profession each month.
So it looks something like this :
PersonID
YEAR
MONTH
DEPARTMENT
PROFESSION
Absence1
Absence2
Absence3
WORKING DAYS OF THE MONTH...
11111
2021
07
HR
ASSISTANT
0
2
0
22
11111
2021
08
HR
ASSISTANT
0
0
0
22
==> So if I'm on a row of July 2021 I need to check the lines from June 2020 to June 2021.
My guess is that I need to add a column to this table who will say (with some kind of loop maybe) "if for the last 12 months (rows) the total number of days of absence equal the number of working days of the last 12 months then "ILL FOR A YEAR OR MORE" for each person (knowing that a person can work in more than one department or more than one profession so she'll have more than one row per month).
But I really have no idea how to actually write it in a script as I usually do very basic things. I'm using SQL SERVER and have 429 207 rows in the table. I'm thinking about doing it in the whole table and not only treating this month's rows because in the dashboard we show an historic.
Your table is heavily denormalized. If you want to represent all this information in the database, I would have expected the following tables, instead of just one:
Person
Department
Illness (list of illnesses)
IllnessAbsence (join table between Person and Illness)
Either way, you can get the information you need with something like this:
I've assumed you want the whole table, so you need a window function
We need to flip the logic on its head: exclude all rows which have no non-absence in the last 12 months
SELECT
PersonID,
YEAR,
MONTH,
DEPARTMENT,
PROFESSION,
ILLNESS1,
ILLNESS2,
ILLNESS3,
[WORKING DAYS OF THE MONTH]
FROM (
SELECT *,
NotIllLast12Months = COUNT(CASE WHEN DATEFROMPARTS(YEAR + 1, MONTH, 1) >= GETDATE()
AND ILLNESS1 + ILLNESS2 + ILLNESS3 = 0 THEN 1 END)
OVER (PARTITION BY ID)
FROM HETP_ABS
) abs
WHERE NotIllLast12Months > 0;

Forcing rows to appear despite data missing

I have a large data set (called input below) which contains a variety of information such as sales dates, transaction dates, payments, sales.
The user can produce a report by year, quarter or month to show the amount of payment in a particular month/quarter/year of a certain sales year. So you could have a payment 5 years after the initial sale, i.e. a payment in 2016 relating to the sales year of 2011.
The user can decide whether they want to have these payment periods by month/quarter/year at the beginning of the code through the use of macro variables (i.e. %let ReportBasis = Year) and ReportBasis can be called on through the rest of the code without manual adjustments.
The report is produced using:
proc sql;
create table report as
select sales_year, &ReportBasis, Sum(Sales) as Sales
from input
group by sales_year, &ReportBasis;
quit;
Now the issue I am having is that if there is no payment in a particular period for all sales years in question, then there is no row for that period. This produces a layout problem.
I require a solution to this which can be dynamic due to the nature of the macro variable (changing from year to month to quarter).
So I have this (example):
2011 Month 11 100
2011 Month 12 250
2011 Month 13 85
2011 Month 15 90
2011 Month 16 300
But I require this:
2011 Month 11 100
2011 Month 12 250
2011 Month 13 85
2011 Month 14 0
2011 Month 15 90
2011 Month 16 300
where there is no actual payment in month 14 in all of my data (even other years 2012, 2013 etc.), so it doesn't show up in my first table, but the second table still cleverly knows to include it.
Thanks in advance.
Here is one solution that assumes that all years and reports are represented in input, although not all combinations:
create table report as
select sy.sales_year, r.rb, Sum(i.Sales) as Sales
from (select distinct sales_year from input) sy cross join
(select distinct &ReportBasis as rb from input) r left join
input i
on i.sales_year = sy.sales_year and i.&ReportBasis = r.&ReportBasis
group by sy.sales_year, r.rb;

SQL DatePart Week, year to reflect fiscal year

I currently have a report that uses DATEPART to return the week a 'car' was returned. However, the business I work for fiscal year starts first Sunday of the year (this instance commencing 03/01/2016 would be week 1). However, using SQL 'DATEPART wk' would return this date is week 2:
Current outcome using DATEPART (wk, year etc):
CarTitle ReturnDate Year Week
Car 1 30/12/2015 2015 53
Car 2 02/01/2016 2016 1
Car 3 03/01/2016 2016 2
Car 4 05/01/2016 2016 2
Car 5 10/01/2016 2016 3
Car 6 17/01/2016 2016 4
Example of expected outcome:
CarTitle ReturnDate Year Week
Car 1 30/12/2015 2015 53
Car 2 02/01/2016 2015 53
Car 3 03/01/2016 2016 1
Car 4 05/01/2016 2016 1
Car 5 10/01/2016 2016 2
Car 6 17/01/2016 2016 3
I can calculate this with the following SQL:
SELECT
CarTitle,
DATEPART(ISO_WEEK, DATEADD(day, 1, ReturnDate))
FROM
dbo.My_Table
However, this depends on your localization settings (which are probably different from mine given how you express dates) and if you use this code throughout your system and then the business decides to change it's method for calculating weeks then you could end up with a big refactorization headache.
I prefer to use a Calendar table for this sort of thing:
CREATE TABLE dbo.Calendar (
calendar_date DATE NOT NULL,
week_number SMALLINT NOT NULL,
is_holiday BIT NOT NULL,
name VARCHAR(30) NOT NULL, -- i.e. 'January 6th, 2016'
CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (calendar_date)
)
You can expand the table as needed, for example if accounting uses a different definition for week of the year than another department then that's easy to accommodate by adding another column. This then makes your query a simple join to get the week number:
SELECT
MT.CarTitle,
MT.ReturnDate,
CAL.week_number
FROM
My_Table MT
INNER JOIN dbo.Calendar CAL ON CAL.calendar_date = MT.ReturnDate
You'll need to populate the table, but that should be a one time effort (populate it for 50 years in advance and it's still a pretty small table) and you can use code similar to my first statement to generate the values - don't enter each date by hand ;) After that you just need to maintain the table if the business logic changes (which is easier than changing all of your queries that deal with dates) or if you get a new requirement that needs a new column.

Year Week column comparison

I have this query that spits out every Week for the past 2 years a company owes us money. I have to narrow the results down based on their starting year and week, which are 2 separate columns. This is my current query. How do I change this so it only shows data where the year is greater or equal to start year and the week is greater or equal to the start week without losing data? So for example if I have a company 023 and its start date is week 5 2012, I'll say year>=2012 and week>=5, but then it will exclude all the weeks in 2013 and 2014 where week is less than 5. I'm not sure how logically to get around that.
SELECT MW.MW_Weeks.Year,
MW.MW_Weeks.Week,
MW.MW_CompanyCodes.cmp_code,
MW.MW_CompanyCodes.stWeek,
MW.MW_CompanyCodes.stYear
FROM MW.MW_Weeks CROSS JOIN
MW.MW_CompanyCodes
WHERE (MW.MW_Weeks.WEDate <= GETDATE())
AND (MW.MW_Weeks.Year > YEAR(GETDATE()) - 2);
Use the following:
year >= 2012 and not (year = 2012 and week < 5)
This will get all data whose year is greater than or equal to 2012 and is not before week five in 2012.

MS Access grouping query spanning start and end dates

I would like to get a running tally of how many widgets were/are rented at any one time, by month, by year. Data is held in an MS Access 2003 db;
Table name: rent_table
Fields:
rentid
startdate
enddate
rentfee
rentcost
bookingfee
Something like; Count number of rentid's that fall between month/year, then group them?
e.g. if a widget was rented from 5th Jan 2014 to 8th April 2014 it would appear as a count in Jan, Feb, Mar and April tally's.
Many thanks.
EDIT
More details (sorry);
Access db is fronted by classic ASP.
If possible I don't want to create any new tables.
No input is required in order to run the report.
There are around 350-400 widgets that could be rented at any one time.
Each widget is rented exclusively.
Report output example;
Month | Year | NumRented
Jan 2014 86
Feb 2014 113
...
Can a query pick up dates within dates? So literally do a count of the table where date >Dec 31st 2013 AND <1st Feb 2014 (to grab a count for all of January 2014) and would that include the example of the rent starting on the 5th Jan? So I could just do twelve counts for each year?
create a calendar table, e.g.
table = cal_yyyymm with one column dt_yyyymm as numeric field
populate the table with ... say 5 or 10 years of data
201401 201402 201403 ... 60 or 120 rows, a small table
make a sql
Select
dt_yyyymm,
count(*) as cnt
From cal_yyyymm
Left Join rent_table
On format(startdate,"yyyymm") >= dt_yyyymm
And dt_yyyymm >= format(enddate,"yyyymm")
think about the complications in the data -- --
widget was rented from 5th Jan 2014 to 8th Jan 2014
and again rented from 11th Jan 2014 to 21st Jan 2014
does this count at 1 or 2 in the month?
if it is 1, then the sql gets more complicated because
the rent_table first needs to have its dates converted
to yyyymm format, and second needs to be de-duped on rentid,
and third then joined to cal_ On the dates...