Would like a way to improve my my SQL query in ASP - sql

I would simply like to get the latest record from the Division_Program column.
The data within the "JMSDay" column data are populated with the seven days of the week. I used an array to abbreviate the days (i.e. Mon thru Sun). the "JMS_UpdateTime" column data uses the following format 8/4/2013 1:02:12 PM
SELECT top 1 *
FROM CensusFacility_Records
WHERE JMSDay = '" & smDateArray (Weekday(date)) & "'
AND Division_Program ='" & divrec &"'
order by JMS_UpdateDateTime desc

WITH Census AS
(
SELECT
*
,ROW_NUMBER() OVER(ORDER BY JMS_UpdateDateTime DESC) AS RowID
FROM CensusFacility_Records
WHERE JMSDay = '" & smDateArray (Weekday(date)) & "'
AND Division_Program ='" & divrec &"'
)
SELECT * FROM Census
WHERE RowID=1;

Related

SQL in MS Access (sum data in a secondary table based on it being between two dates + matching names in records)

I have two tables:
Salary Payslips:
Payslip ID
Salary Deduction
Payslip Date
Employee Name
1
calc
5/29/2022
ABC
2
calc
4/29/2022
ABC
3
calc
3/29/2022
ABC
4
calc
2/28/2022
ABC
Salary Deductions:
Deduction ID
Deduction Date
Deduction Amount
Employee Name
1
3/30/2022
50
ABC
2
5/10/2022
100
ABC
3
5/15/2022
100
ABC
I have two tables "Salary Payslips" and "Salary Deductions." Deductions are removed from the total payslip amount (not shown here because its unnecessary to address the problem).
I am trying to calculate the total accrued deductions per salary cycle. (4/29/2022 -> 5/29/2022 is one salary cycle). In the example above, the total deductions between the two dates (i.e. the salary cycle) should be 200. I would want to have that number show up in the Salary Deduction field with Payslip ID=1 in the Salary Payslips table.
In the same fashion, the deduction on 3/30/2022 should show up in the salary payslips table at the record with payslip id =2.... and so on. The deduction amount in the payslip id = 3 should be zero since there were no deductions in during the period between 2/28-3/29.
This should be done where the employee name is identical in both tables, so "ABC has 50 deducted from salary in cycle between 2/28/2022 and 3/29/2022" etc.
All of this should be updated recursively in a form. Hence, the control should be able to query the tables for the data and parse that onto the corresponding field in the form (and by association, the table).
Consider the DSum domain aggregate which is available as an expression function, VBA function, and SQL function in MS Access (frontend GUI but not backend connection). Similarly, you can use DLookUp (which I advised on your previous question) calling SUM() in expression argument.
Specifically, sum the Salary Deduction column in other table by corresponding Employee Name and where Deduction Date falls within date range of PaySlip Date and less than one month after using DateAdd.
Expression (set to control source of [Salary Deduction] textbox in form design of [Salary PaySlip] form)
=DSum("[Deduction Amount]",
"[Salary Deductions]",
"[Employee Name] = '" & [Employee Name] & "' AND
[Deduction Date] >= #" & [PaySlip Date] & "#
AND < #" & DateAdd("m", 1, [PaySlip Date]) & "#")
VBA (programmatically calculate control source)
Forms![Salary PaySlip]![Salary Deduction] = DSum( _
"[Deduction Amount]", _
"[Salary Deductions]", _
"[Employee Name] = '" & Forms![Salary PaySlip]![Employee Name] & "' AND " _
& "[Deduction Date] >= #" & Forms![Salary PaySlip]![PaySlip Date] & "#" _
& " AND < #" & DateAdd("m", 1, Forms![Salary PaySlip]![PaySlip Date]) & "#" _
)
SQL
UPDATE (using DSum to save data to table –cannot use subquery)
UPDATE [Salary PaySlip] p
SET p.[Salary Deduction] = DSum(
"[Deduction Amount]",
"[Salary Deductions]",
"[Employee Name] = '" & p.[Employee Name] & "' AND
[Deduction Date] >= #" & p.[PaySlip Date] & "#
AND < #" & DateAdd("m", 1, p.[PaySlip Date]) & "#"
)
Alternatively, you can use a correlated aggregate subquery which can have performance issues for large enough data. Hopefully, one day soon the MS Access team will add support for window functions (per SQL ANSI 2003) to the Access SQL dialect!
SELECT (using correlated aggregate subquery)
SELECT p.[PaySlip ID],
(SELECT SUM([Deduction Amount])
FROM [Salary Deductions] d
WHERE d.[Employee Name] = p.[Employee Name]
AND d.[Deduction Date] >= p.[PaySlip Date]
AND < DateAdd('m', 1, p.[PaySlip Date])
) AS [Salary Deduction],
p.[PaySlip Date]
p.[Employee Name]
FROM [Salary Payslips] p

Multiple columns from one column

I track the aging of customer invoices.
The below code example returns the balance of customer invoices by customer that are between 0 and 30 days old.
However, I want to run one query that pulls separate columns into Excel for each customer's balance aged between 0 and 30 days, 31 and 60, 61 and 90, and finally over 90 days.
I am hoping to pull this into Excel so the columns are as follows-
Customer Number, Customer Name, Balance(That is under 30 days old), Balance(30-59 days), Balance(60-90), Balance(Over 90)
vtSql = ""
vtSql = vtSql & " SELECT CUSTNUM, CUSTNAME, SUM(BALANCE) "
vtSql = vtSql & " FROM VIEWALLINVOICES "
vtSql = vtSql & " WHERE BALANCE <> '0' AND INVDATE BETWEEN #" & Application.Text(Range("TODAY") - 30, "mm/dd/yyyy") & "# AND #" & Application.Text(Range("TODAY"), "mm/dd/yyyy") & "#"
vtSql = vtSql & " GROUP BY CUSTNUM, CUSTNAME "
vtSql = vtSql & " ORDER BY SUM(BALANCE) DESC;"
I am using a MS Access database and I am pulling this directly into Excel using an ADODB Connection and "Microsoft.Jet.OLEDB.4.0".
You seem to want conditional aggregation. In MS-Access, you should be able to phrase this as:
SELECT CUSTNUM, CUSTNAME,
SUM(IIF(INVDATE BETWEEN DateAdd('d', -30, date()) AND date() , BALANCE, 0)) AS BALANCE_0_30,
SUM(IIF(INVDATE BETWEEN DateAdd('d', -60, date()) AND DateAdd('d', -31, date()), BALANCE, 0)) AS BALANCE_31_60,
SUM(IIF(INVDATE BETWEEN DateAdd('d', -90, date()) AND DateAdd('d', -61, date()), BALANCE, 0)) AS BALANCE_61_90,
SUM(IIF(INVDATE <= DateAdd('d', -91, date()) , BALANCE, 0)) AS BALANCE_OVER_91
FROM VIEWALLINVOICES
GROUP BY CUSTNUM, CUSTNAME
This computes the dates ranges dynamically by offseting the current date - which is how I understood your question.

Access database Date type mismatch

'Sql = "Select ItemName,Count(itemID) from tblItem where Item ='" & "A" & "' AND ExpireDate < '" & Now().Date() & "' Group By ItemName"
I'm FACING Datatype miss match in this query in DATE Field....
How could I do this?
I think you need to escape your date with the pound "#" symbol.
Try this:
"Select ItemName,Count(itemID) from tblItem where Item ='" & "A" & "' AND ExpireDate < #" & Now().Date() & "# Group By ItemName"
If you want to filter with current date in MS Access just use Date. In where clause date should be surrounded by # sign
SQL = "Select ItemName,Count(itemID) from tblItem where Item ='" & "A" & "' AND ExpireDate < #" & Date & "# Group By ItemName"
Use the Date() function of Access:
Sql = "Select ItemName, Count(itemID) From tblItem Where Item ='A' And ExpireDate < Date() Group By ItemName"

(using join) I get not contained in either an aggregate function or the GROUP BY error

I get the following error.
[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'STATS.VisitorIP' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I used VISITORIP column in both select lists. I used GROUP BY clause in one of them so I addded VISITORIP to it. But I dont have GROUP BY clause in other select so did not add it. Why do I receive this error?
SELECT S.VISITORIP, S.HTTPADDRESS, S.DATEENTERED
FROM STATS S
JOIN (SELECT S1.VISITORIP, MAX(S1.DATEENTERED) FROM STATS S1 WHERE DATEENTERED BETWEEN '" & OnlineTime & "' AND '" & NOW() & "') S1
ON S.VISITORIP = S1.VISITORIP AND S.DATEENTERED = S1.DATEENTERED
WHERE S.DATEENTERED BETWEEN '" &TIME& "' AND '" & NOW() & "'
GROUP BY S.VISITORIP, S.HTTPADDRESS, S.DATEENTERED
ORDER BY S.DATEENTERED DESC
You need the GROUP BY in the nested subquery because you are trying to get the MAX DATEENTERED for each VISITORIP. VISITORIP exists in the SELECT for that subquery, so you need the GROUP BY in there also in order for it to return the latest date for each visitorip.
SELECT S.VISITORIP, S.HTTPADDRESS, S.DATEENTERED
FROM STATS S
JOIN (SELECT S1.VISITORIP, MAX(S1.DATEENTERED) FROM STATS S1 WHERE DATEENTERED BETWEEN '" & OnlineTime & "' AND '" & NOW() & "' GROUP BY S1.VISITORIP) S1
ON S.VISITORIP = S1.VISITORIP AND S.DATEENTERED = S1.DATEENTERED
WHERE S.DATEENTERED BETWEEN '" &TIME& "' AND '" & NOW() & "'
GROUP BY S.VISITORIP, S.HTTPADDRESS, S.DATEENTERED
ORDER BY S.DATEENTERED DESC
This (nested query) is not valid:
SELECT S1.VISITORIP, MAX(S1.DATEENTERED)
FROM STATS S1
WHERE DATEENTERED BETWEEN '" & OnlineTime & "' AND '" & NOW() & "'
It should be:
SELECT S1.VISITORIP, MAX(S1.DATEENTERED) AS DATEENTERED
FROM STATS S1
WHERE DATEENTERED BETWEEN '" & OnlineTime & "' AND '" & NOW() & "'
GROUP BY S1.VISITORIP
Your Inner select uses MAX on DATEENTERED but does not include a groupby on the VisitorIP.
SELECT S.VISITORIP, S.HTTPADDRESS, S.DATEENTERED
FROM STATS S
JOIN (SELECT S1.VISITORIP, MAX(S1.DATEENTERED)
FROM STATS S1
WHERE DATEENTERED BETWEEN '" & OnlineTime & "' AND '" & NOW() & "'
GROUPBY S1.VISITORIP) S1
ON S.VISITORIP = S1.VISITORIP AND S.DATEENTERED = S1.DATEENTERED
WHERE S.DATEENTERED BETWEEN '" &TIME& "' AND '" & NOW() & "'
GROUP BY S.VISITORIP, S.HTTPADDRESS, S.DATEENTERED
ORDER BY S.DATEENTERED DESC
You're getting the error because your subselect in the JOIN:
SELECT S1.VISITORIP, MAX(S1.DATEENTERED) FROM STATS S1 WHERE DATEENTERED BETWEEN '" & OnlineTime & "' AND '" & NOW() & "'
Is attempting to aggregate "DATEENTERED", but needs to group on "VISITORIP" in order to do so.
Try:
SELECT S1.VISITORIP, MAX(S1.DATEENTERED) FROM STATS S1 WHERE DATEENTERED BETWEEN '" & OnlineTime & "' AND '" & NOW() & "' GROUP BY S1.VISITORIP

Building up a monthly total from past 12 months

CurrentMonth = Month(CurrentDate)
CurrentYear = Year(CurrentDate)
SQL = "SELECT Spent, MONTH(Date) AS InvMonth, YEAR(Date) As InvYear FROM Invoices WHERE YEAR(Date) = '" & CurrentYear & "' AND MONTH(Date) = '" & CurrentMonth & "'"
RecordSet.Open SQL, Connection, adOpenStatic, adLockOptimistic, adCmdText
Do Until RecordSet.EOF
MTotal(i) = MTotal(i) + RecordSet.Fields("Spent")
RecordSet.MoveNext
Loop
RecordSet.Close
This is the code I currently have to build up a total spent for a given month.
I wish to expand this to retrieve the totals per month, for the past 12 months.
The way I see to do this would be to loop backwards through the CurrentMonth value, and if CurrentMonth value reaches 0 roll the value of CurrentYear back 1. Using the loop variable (i) to build up an array of 12 values: MTotal()
What do you guys think?
A group by should get you on the way.
SELECT TOP 12
SUM(Spent) AS Spent
, MONTH(Date) AS InvMonth
, YEAR(Date) AS InvYear
FROM
Invoices
GROUP BY
YEAR(Date), MONTH(Date)
WHERE DATEDIFF(mm, Date, GETDATE(()) < 12
Josh's DATEDIFF is a better solution than my original TOP and ORDER BY
I would tackle this by "rounding" the date to the Month, and then Grouping by that month-date, and totalling the Spent amount:
SELECT SUM(Spent) AS [TotalSpent],
DATEADD(Month, DATEDIFF(Month, 0, [Date]), 0) AS [MonthDate]
FROM Invoices
WHERE [Date] >= '20080301'
AND [Date] < '20090301'
GROUP BY DATEADD(Month, DATEDIFF(Month, 0, [Date]), 0)
ORDER BY [MonthDate]
The [MonthDate] can be formatted to show Month / Date appropraitely, or in separate columns.
The WHERE clause can be parameterised to provide a suitable range of records to be included
The only problem with this is that I require a monthly total, for each of the past 12 months rather then the total for the past 12 months. Otherwise I see how improving the SQL rather then using vb6 code oculd be a better option.
The solution I came up with would be :
For i = 0 To 11
If CurrentMonth = 0 Then
CurrentMonth = 12
CurrentYear = CurrentYear - 1
End If
SQL = "SELECT Spent, MONTH(Date) AS InvMonth, YEAR(Date) As InvYear FROM Invoices WHERE YEAR(Date) = '" & CurrentYear & "' AND MONTH(Date) = '" & CurrentMonth & "'"
RecordSet.Open SQL, Connection, adOpenStatic, adLockOptimistic, adCmdText
Do Until RecordSet.EOF
MTotal(i) = MTotal(i) + RecordSet.Fields("Spent").Value
RecordSet.MoveNext
Loop
RecordSet.Close
CurrentMonth = CurrentMonth - 1
Next
I believe this should work as expected. However I still look forward to seeing what solutions you guys can come up, or if anyone spots an issue with ym fix.