tracking IP addresses - sql

I want to track IP addresses visited my website. I want to know what time and what page they visit. I store ip address in VISITORIP, date entered in DATEENTERED and page URL in HTTPADDRESS columns.
I want to group them by dates. My outcome should be like:
TIME PAGE
7/12/2009
3:16:27 PM ?Section=products&SubSection=products&CATEGORYID=1
2:46:50 PM ?Section=products&SubSection=products&CATEGORYID=8
2:20:45 PM ?Section=products&SubSection=products&CATEGORYID=11
7/11/2009
9:34:28 AM ?Section=products&SubSection=products&CATEGORYID=7
9:33:31 AM ?Section=products&SubSection=products&CATEGORYID=2
7/10/2009
9:53:16 PM ?Section=products&SubSection=products&CATEGORYID=9
9:34:14 PM ?Section=products&SubSection=products&CATEGORYID=4
9:27:11 PM ?Section=products&SubSection=products&CATEGORYID=3
9:15:47 PM ?Section=products&SubSection=products&CATEGORYID=15
Problem is, I could not group them by dates. I get the outcome as:
07/12/2009
7/12/2009 3:16:27 PM /html/default.aspProcess=HomeNewSeason&IMAGECONTENT=bg_home_newtaste.gif
7/12/2009 3:16:27 PM /html/default.aspProcess=HomeBestSeller&IMAGECONTENT=bg_home_customerschoice.gif
07/12/2009
7/12/2009 3:16:27 PM /html/default.aspProcess=HomeNewSeason&IMAGECONTENT=bg_home_newtaste.gif
7/12/2009 3:16:27 PM /html/default.aspProcess=HomeBestSeller&IMAGECONTENT=bg_home_customerschoice.gif
07/09/2009
7/9/2009 5:37:02 PM /html/default.aspSection=checkout
07/09/2009
7/9/2009 5:37:02 PM /html/default.aspSection=checkout
07/09/2009
7/9/2009 5:37:02 PM /html/default.aspSection=checkout
My codes:
<%
Case "TrackIP"
IPADDRESS = Request.QueryString("IPADDRESS")
SQL = "SELECT CONVERT(VARCHAR(10), DATEENTERED, 101) AS DATEENTERED"
SQL = SQL & " FROM STATS"
SQL = SQL & " WHERE VISITORIP = '"& IPADDRESS &"'"
SQL = SQL & " GROUP BY DATEENTERED"
SQL = SQL & " ORDER BY DATEENTERED DESC"
Set objDateEntered = objConn.Execute(SQL)
%>
<table>
<thead>
<tr>
<th>Time</th>
<th>Page</th>
</tr>
</thead>
<tbody>
<% Do While Not objDateEntered.EOF %>
<tr class="row-title">
<td colspan="2"><%=objDateEntered("DATEENTERED")%></td>
</tr>
<%
SQL = "WITH LASTVISIT AS ("
SQL = SQL & " SELECT VISITORIP, MAX(DATEENTERED) AS DATEENTERED"
SQL = SQL & " FROM STATS"
SQL = SQL & " WHERE VISITORIP = '"& IPADDRESS &"' AND CONVERT(VARCHAR(10), DATEENTERED, 101) = CONVERT(VARCHAR(10), '"& objDateEntered("DATEENTERED") &"', 101)"
SQL = SQL & " GROUP BY VISITORIP"
SQL = SQL & " )"
SQL = SQL & " SELECT STATS.VISITORIP, STATS.HTTPADDRESS, STATS.DATEENTERED"
SQL = SQL & " FROM STATS"
SQL = SQL & " INNER JOIN LASTVISIT"
SQL = SQL & " ON LASTVISIT.VISITORIP = STATS.VISITORIP AND LASTVISIT.DATEENTERED = STATS.DATEENTERED"
SQL = SQL & " ORDER BY STATS.DATEENTERED DESC"
Set objTrackIP = objConn.Execute(SQL)
%>
<% Do While Not objTrackIP.EOF %>
<tr class="row-a">
<td><%=objTrackIP("DATEENTERED")%></td>
<td class=""><%=objTrackIP("HTTPADDRESS")%></td>
</tr>
<%
objTrackIP.MoveNext
Loop
%>
<%
objDateEntered.MoveNext
Loop
%>
</tbody>
</table>
edit: I think problem is with my outer query. But I grouped them by DATEENTERED field, I dont know what else can I do.

First query should be
"SELECT
DISTINCT CONVERT(VARCHAR(10), DATEENTERED, 101) AS vDATE
FROM
STATS
WHERE
VISITORIP = '"& IPADDRESS &"'"
ORDER BY
DATEENTERED DESC"
then print the vData column
and the 2nd SQL
SELECT
VISITORIP, HTTPADDRESS, CONVERT(VARCHAR(8), DATEENTERED, 8) AS vTIME
FROM
STATS
WHERE
CONVERT(VARCHAR(10), DATEENTERED, 101) = '" & objDateEntered("vDATE") &"'
AND VISITORIP = '"& IPADDRESS &"'
ORDER BY VISITORIP ASC, DATEENTERED DESC
I think this will do the trick..

The problem is in next code line:
SELECT CONVERT(VARCHAR(10), DATEENTERED, 101) AS DATEENTERED
and then you group by this date
GROUP BY DATEENTERED
ORDER BY DATEENTERED DESC
You group and order by the varchar.
As I think, you need to use another alias to date when you convert it ro varchar, but you really need to order by dateentered that is datetime type.

It you're trying to get some visitor tracking happening have you thought of using something like Google Analytics?

Related

Is there a way to do a full join of two tables on a composite key using a SQL query in Excel VBA?

I am trying to write a SQL query in Excel that joins two tables (Table A and Table B) using a composite key and returns matching records from Table B, as well as any in Table B that do not match.
The two tables have different dimensions and the data is as follows:
Table A
ID Date Timestamp Time Event Type Time Event Type Desc. ...
----- ----------- ------------- ----------------- ----------------------- -----
123 10/5/2020 8:05:00 AM P10 Clock In ...
123 10/5/2020 11:00:00 AM P15 Meal Start ...
123 10/5/2020 11:30:00 PM P25 Meal End ...
123 10/5/2020 6:30:00 PM P20 Cock Out ...
... ... ... ... ...
Table B
ID Date Scheduled Start Scheduled End ...
----- ----------- ----------------- --------------- -----
123 10/5/2020 8:00:00 AM 6:00:00 PM ...
123 10/6/2020 10:00:00 AM 4:00:00 PM ...
123 10/7/2020 9:00:00 AM 4:00:00 PM ...
123 10/8/2020 12:00:00 AM 12:00:00 AM ...
123 10/9/2020 12:00:00 PM 7:00:00 PM ...
124 10/5/2020 9:00:00 AM 4:00:00 PM ...
... ... ... ...
The composite key is a combination of ID and Date. With the code below I am able to join the two tables and output a table that shows (for each ID on each day they clocked in) the Scheduled Start time, Clock In time, Scheduled End time, Clock Out time, and some other columns.
sql_query = _
"SELECT [a].[ID], FORMAT([a].[Date], 'mm/dd/yyyy'), " & _
"FORMAT([b].[Scheduled Start], 'hh:mm:ss AM/PM'), " & _
"FORMAT(MIN(CDATE([a].[Timestamp])),'hh:mm:ss AM/PM') AS [Clock In Time], " & _
"FORMAT([b].[Scheduled End], 'hh:mm:ss AM/PM'), " & _
"FORMAT(MAX(CDATE([a].[Timestamp])),'hh:mm:ss AM/PM') AS [Clock Out Time] " & _
"FROM [CLOCKINREPORT#csv] AS [a] " & _
"LEFT JOIN [SCHEDULEREPORT#csv] AS [b] " & _
"ON [a].[ID] = [b].[ID] AND [b].[Date] = [a].[Date] " & _
"WHERE ([a].[Date] BETWEEN #" & Format(sWeekPer, "yyyy-mm-dd") & "# AND #" & Format(eWeekPer, "yyyy-mm-dd") & _
"#) AND ([a].[Time Event Type] = 'P10' OR [a].[Time Event Type] = 'P20')" & _
"GROUP BY [a].[ID], [a].[Date], [b].[Scheduled Start], [b].[Scheduled End] "
Output Table
ID Date Scheduled Start Clock In Time Scheduled End Clock Out Time ...
----- ----------- ----------------- --------------- --------------- ----------------
123 10/5/2020 8:00:00 AM 8:05:00 AM 6:00:00 PM 6:30:00 PM ...
... ... ... ... ... ...
What I would also like to show records on days that the ID was scheduled but did not work (i.e., if '123' was scheduled on '10/6/2020' but no combination of the composite key, ID and Date, are not found in Table A, null values should be displayed in the Clock In Time and Clock Out Time columns). One issue that is present in the data is that on days when an ID did not clock in or clock out, there are no records associated with that date in Table A.
Desired Output
ID Date Scheduled Start Clock In Time Scheduled End Clock Out Time ...
----- ----------- ----------------- --------------- --------------- ----------------
123 10/5/2020 8:00:00 AM 8:05:00 AM 6:00:00 PM 6:30:00 PM ...
123 10/6/2020 10:00:00 AM NULL 4:00:00 PM NULL ...
... ... ... ... ... ...
My understanding is that Microsoft ACE 12.0 does not support a FULL JOIN and requires a UNION to pull off what I would like to do. I must admit I am quite the beginner in SQL and the UNION's I have tried based on a few stackoverflow questions have not worked. I would much appreciate any help solving this problem.
Consider the workaround query for FULL JOIN in MS Access. However, for readability and maintainability avoid messy concatenation, line breaks, quote handling, and date # enclosures in VBA. Instead, save your SQL in a separate .SQL file or better for efficiency save the query in the corresponding MS Access database and run ADO parameterization on the BETWEEN dates.
SQL (save as MS Access stored query or .SQL file; notice ? for parameter placeholders)
SELECT c.[ID]
, FORMAT(c.[Date], 'mm/dd/yyyy')
, FORMAT(s.[Scheduled Start], 'hh:mm:ss AM/PM')
, FORMAT(MIN(CDATE(c.[Timestamp])),'hh:mm:ss AM/PM') AS [Clock In Time]
, FORMAT(s.[Scheduled End], 'hh:mm:ss AM/PM')
, FORMAT(MAX(CDATE(c.[Timestamp])),'hh:mm:ss AM/PM') AS [Clock Out Time]
FROM [CLOCKINREPORT#csv] AS c
LEFT JOIN [SCHEDULEREPORT#csv] AS s
ON c.[ID] = s.[ID] AND s.[Date] = c.[Date]
WHERE (c.[Date] BETWEEN ? AND ?)
AND (c.[Time Event Type] = 'P10' OR c.[Time Event Type] = 'P20')
GROUP BY c.[ID]
, c.[Date]
, s.[Scheduled Start]
, s.[Scheduled End]
UNION
SELECT s.[ID]
, FORMAT(c.[Date], 'mm/dd/yyyy')
, FORMAT(s.[Scheduled Start], 'hh:mm:ss AM/PM')
, FORMAT(MIN(CDATE(c.[Timestamp])),'hh:mm:ss AM/PM') AS [Clock In Time]
, FORMAT(s.[Scheduled End], 'hh:mm:ss AM/PM')
, FORMAT(MAX(CDATE(c.[Timestamp])),'hh:mm:ss AM/PM') AS [Clock Out Time]
FROM [CLOCKINREPORT#csv] AS c
RIGHT JOIN [SCHEDULEREPORT#csv] AS s
ON c.[ID] = s.[ID] AND s.[Date] = c.[Date]
WHERE (c.[Date] BETWEEN ? AND ?)
AND (c.[Time Event Type] = 'P10' OR c.[Time Event Type] = 'P20')
GROUP BY s.[ID]
, c.[Date]
, s.[Scheduled Start]
, s.[Scheduled End]
VBA (using ADO to connect to Access database)
Sub RunSQL()
' REFERENCE THE MICROSOFT ACTIVEX DATA OBJECTS XX.X LIBRARAY '
Dim conn As ADODB.Connection, cmd As New ADODB.Command, rs As ADODB.Recordset
Dim StrQuery As String
' READ SQL QUERY FROM FILE
With CreateObject("Scripting.FileSystemObject")
StrQuery = .OpenTextFile("C:\Path\To\myQuery.sql", 1).readall
End With
' OPEN DB CONNECTION
Set conn = New ADODB.Connection
conn.Open "DRIVER=Microsoft Access Driver (*.mdb, *.accdb);DBQ=C:\Path\To\Database\File.accdb;"
' DEFINE COMMAND OBJECT
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandType = adCmdText ' OR BETTER IF USING SAVED QUERY: adCmdStoredProc
.CommandText = StrQuery ' OR BETTER IF USING SAVED QUERY: "myStoredAccessQuery"
' BIND 4 DATE PARAMETERS FOR FOUR ? IN SQL, ASSUMING sWeekPer AND eWeekPer ARE VBA DATES
.Parameters.Append .CreateParameter("dtparam1", adDate, adParamInput, , sWeekPer)
.Parameters.Append .CreateParameter("dtparam2", adDate, adParamInput, , eWeekPer)
.Parameters.Append .CreateParameter("dtparam3", adDate, adParamInput, , sWeekPer)
.Parameters.Append .CreateParameter("dtparam4", adDate, adParamInput, , eWeekPer)
End With
' BIND OUTPUT TO RECORDSET
Set rs = cmd.Execute
' ... USE rs AS NEEDED ...
' CLOSE AND RELEASE OBJECTS
rs.Close: conn.Close
Set rs = Nothing: Set cmd = Nothing: Set conn = Nothing
End Sub

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"

Adding an IFNULL condition for a count

I am having an issue getting a record produced if my count = 0.
Basically my query is counting logons based on some criteria, but if there has never been a logon for a specific customerID I still want it to show as 0.
I have tried IFNULL on the count but with no joy.
SELECT
CUSTOMERID,
CASE
WHEN STATUSCODE = 600 THEN 'Successful Logon'
ELSE 'Unsuccessful Logon'
END as LogonStatus,
COUNT( * ) COUNTOFACCOUNTS
FROM
SCEMEA.TABLENAME
WHERE
CUSTOMERID in ('"+join(Parameters!CustomerID.Value, "','")+"')
AND (Cast(DATETIME as Date) >= '"& Format(Parameters!FromDate.Value, "yyyy-MM-dd") & "'
AND Cast(DATETIME as Date) <= '" & Format(Parameters!ToDate.Value, "yyyy-MM-dd") & "')
AND COMPONENTDESCRIPTION = 'RandomText'
AND METHOD = 'RandomText'
GROUP BY
CUSTOMERID,
CASE
WHEN STATUSCODE = 600 THEN 'Successful Logon'
ELSE 'Unsuccessful Logon'
END
ORDER BY
CUSTOMERID ASC
Please let me know if you need anymore information, any help would be appreciated.

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

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;

(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