在Access查询的SELECT子句中列出每一天

时间:2014-07-09 10:50:49

标签: sql ms-access asp-classic

我有一个包含下表的Access数据库。

tblFaultCall
------------
ID : Autonumber
strName
strPhone
dtmDateOpen : Date/Time (date call logged)
dtmDateClosed : Date/Time (date call closed)
dtmTime : Date/Time (time call logged)
strStatus (always 'Open', 'Pending' or 'Closed')
strCategory (always one of 10 categories, held as as list in tblCatgory, and used in lookup lists in the ASP web page)
strFaultDesc 
strResolution
strCallOwner
dtmDatePending : Date/Time (date call set to pending, if it ever was)

呼叫以Open状态进入。如果用户设置为挂起,则使用当前日期填充dtmDatePending 如果用户在完成呼叫时将呼叫设置为已关闭,则dtmDateClosed将填充当前日期。
并非所有通话都设置为待处理 有些日子,用户不会更改呼叫状态,因为他们正在做其他事情。此外,周末没有活动。

我想监控来电者的活动。

我有一个如下查询(在循环中的经典ASP中,每个用户都有一个变量strCallOwner,日期由用户在上一页中设置)

SELECT dtmDateClosed, Count(ID) AS CallsClosed 
FROM tblFaultCall " 
WHERE strCallOwner = """ & strCallOwner & """ 
GROUP BY dtmDateClosed 
HAVING dtmDateClosed BETWEEN  #"& FromMonth & "/" & FromDay & "/" & FromYear &"# and #"& ToMonth & "/" & ToDay & "/" & ToYear &"#  

这很好,并给我输出如下

Day Calls Closed
09/04/2014  4
15/04/2014  4
16/04/2014  2
25/04/2014  1
30/04/2014  1
01/05/2014  7

我们需要清楚地看到用户没有做过任何活动。因此,我希望能够在HAVING子句中显示该期间的每一天(即使那天没有呼叫关闭,如果是周末,我希望结果中的某些内容表明它是周末的一天)。我还想要一个基于dtmDatePending的附加呼叫数列。

我希望它看起来像这样

Day         Calls Closed    Calls Pended
Wed 09/04/14    4           0
Thu 10/04/14    0           0
Fri 11/04/14    0           1
Sat 12/04/14    -           -
Sun 13/04/14    -           -
Mon 14/04/14    0           1
Tue 15/04/14    0           0
Wed 16/04/14    2           1

我在ASP中填充了一个表格,但实际上它是我坚持的查询。

我知道我需要第二列和第三列的外连接,但我需要知道如何为第一列创建天数列表。我不知道在Access查询中是否可以这样做?我可能不得不在ASP中使用数组?或者在数据库中创建一个额外的表?

感谢。

编辑 - 感谢到目前为止的回复,我有一个工作版本给我CallsClosed,如下所示

SELECT d.dtmDate, Count(fc.ID) AS CallsClosed
FROM [select distinct dtmDateClosed as dtmDate
      from tblFaultCall
      where dtmDateClosed BETWEEN #5/20/14# and #5/30/14#
     ]. AS d LEFT JOIN [select fc.*
      from tblFaultCall as fc
      where fc.strCallOwner = 'Ben Hamilton'
     ]. AS fc ON fc.dtmDateClosed = d.dtmDate
GROUP BY d.dtmDate
ORDER BY d.dtmDate;

此报告

dtmDate     CallsClosed
20/05/2014  5
21/05/2014  16
22/05/2014  0
23/05/2014  5
27/05/2014  0
28/05/2014  5
29/05/2014  2
30/05/2014  2

这些数字是正确的,因为我已交叉检查。

但是,我试图修改此内容以包含另一个用于附加案例的列,如下所示

SELECT d.dtmDate, Count(fc.ID) AS CallsClosed, COUNT(fp.ID) AS CallsPended
FROM ([select distinct dtmDateClosed as dtmDate
      from tblFaultCall
      where dtmDateClosed BETWEEN #5/20/14# and #5/30/14#
     ]. AS d LEFT JOIN [select fc.*
      from tblFaultCall as fc
      where fc.strCallOwner = 'Ben Hamilton' AND fc.strStatus = 'Closed'
     ]. AS fc ON fc.dtmDateClosed = d.dtmDate) LEFT JOIN [SELECT fp.ID, fp.dtmDatePending
FROM tblFaultCall AS fp 
WHERE fp.strCallOwner = 'Ben Hamilton' ]. AS fp ON fp.dtmDatePending = d.dtmDate
GROUP BY d.dtmDate
ORDER BY d.dtmDate;

这样运行,但由于某种原因报告错误数字: -

dtmDate     CallsClosed CallsPended
20/05/2014  4           0
21/05/2014  16          0
22/05/2014  0           0
23/05/2014  15          15
27/05/2014  0           0
28/05/2014  20          20
29/05/2014  2           0
30/05/2014  2           0

2014年5月23日,它应该报告5个已结,并且有3个未决。其他日子也是错的。

编辑11/07/14

@Gord Thompson提供的SQL效果很好。但我正在努力参与查询。部分问题是我正在循环遍历包含用户列表的另一个记录集;

<%@ Language="VBScript" %>
<%' Option Explicit %>  
<HTML>
<HEAD>
<title>Fault Call - User Activity Stats</title>
</HEAD>
<BODY>
<% 

Dim FCConnString, FCConn

FCConnString="PROVIDER=Microsoft.Jet.OLEDB.4.0;" & _ 
    "Data Source=" & Server.MapPath("/bactu/spoc/db/FaultCall.mdb") 

set FCConn = CreateObject("ADODB.Connection") 
FCConn.Open(FCConnString)

Dim RSUserDays, SQLUserDays, cmdUserDays 'As ADODB.Command
Dim FromDay, FromMonth, FromTo, ToDay, ToMonth, ToYear
Dim RSUserList, SQLUserList, strCallOwner
Const adParamInput = 1
Const adDBDate = 133
const adVarWChar = 202

FromDay = Request.QueryString("from_day")
FromMonth = Request.QueryString("from_month")
FromYear = Request.QueryString("from_year")

ToDay = Request.QueryString("to_day")
ToMonth = Request.QueryString("to_month")
ToYear = Request.QueryString("to_year")

SQLUserList = "SELECT strCallOwner FROM tblCallOwner WHERE ID in (6, 12, 20, 21, 28, 30)"

SQLUserDays = "SELECT d.dtmDate, fc.ClosedCount, fp.PendingCount " & _
        "FROM " & _
            "( " & _
                "( " & _
                    "SELECT DISTINCT dtmDateOpen AS dtmDate " & _
                    "FROM tblFaultCall " & _
                    "WHERE dtmDateOpen BETWEEN ? AND ? " & _
                ") AS d " & _
                "LEFT JOIN " & _
                "( " & _
                    "SELECT dtmDateClosed, COUNT(*) AS ClosedCount " & _
                    "FROM tblFaultCall " & _
                    "WHERE strCallOwner = ? " & _
                    "GROUP BY dtmDateClosed " & _
                ") AS fc ON d.dtmDate = fc.dtmDateClosed " & _
            ") " & _
            "LEFT JOIN " & _
            "( " & _
                "SELECT dtmDatePending, COUNT(*) AS PendingCount " & _
                "FROM tblFaultCall " & _
                "WHERE strCallOwner = ? " & _
                "GROUP BY dtmDatePending " & _
            ") AS fp ON d.dtmDate = fp.dtmDatePending"

'Create and Open Recordset for UserList
Set RSUserList = Server.CreateObject("ADODB.Recordset")
RSUserList.Open SQLUserList, FCConn, 3, 3

'create ADODB.Command object cmdUserDays and set CommandText, ActiveConnection properties
Set cmdUserDays = CreateObject("ADODB.Command")
cmdUserDays.ActiveConnection = FCConn
cmdUserDays.CommandText = SQLUserDays

'Append cmdUserDays parameters - CreateParameter(Name, Type, Direction, SizeIfString, Value)
cmdUserDays.Parameters.Append cmdUserDays.CreateParameter("QueryFromDate", adDBDate, adParamInput, , DateSerial(FromYear, FromMonth, FromDay))
cmdUserDays.Parameters.Append cmdUserDays.CreateParameter("QueryToDate", adDBDate, adParamInput, , DateSerial(ToYear, ToMonth, ToDay))

'we do not know the strCallOwner yet, but must assign, so default value of "Nothing")
cmdUserDays.Parameters.Append cmdUserDays.CreateParameter("QueryCallOwner1", adVarWChar, adParamInput, 255, "Nothing")
cmdUserDays.Parameters.Append cmdUserDays.CreateParameter("QueryCallOwner2", adVarWChar, adParamInput, 255, "Nothing")

'create recordset from command's execute method
Set RSUserDays = cmdUserDays.Execute

'Iterate through RSUserList using a DO loop, display tables
Do While Not RSUserList.EOF 
strCallOwner = RSUserList("strCallOwner")

'set the 2 command params for call owner, re-execute command - I think this is the bit which is not working
cmdUserDays("QueryCallOwner1") = strCallOwner
cmdUserDays("QueryCallOwner2") = strCallOwner
Set RSUserDays = cmdUserDays.Execute

%>

<b><%=RSUserList("strCallOwner")%></b>
<%'Response.Write(cmdUserDays.CommandText)%>
<table border="1px">        
    <tr>
        <th>Day</th>
        <th>Calls Closed</th>   
        <th>Calls Pended</th>
    </tr>
    <%Do While not RSUserDays.EOF %>
    <tr>
        <td><%= RSUserDays("dtmDate")%>
        <% DayOfWeek = DatePart("W", RSUserDays("dtmDate"))

        Select Case DayOfWeek
        Case 1 Response.Write " Sun"
        Case 2 Response.Write " Mon"
        Case 3 Response.Write " Tue"
        Case 4 Response.Write " Wed"
        Case 5 Response.Write " Thu"
        Case 6 Response.Write " Fri"
        Case 7 Response.Write " Sat"
        End Select%></td>

        <td><%= RSUserDays("ClosedCount") %></td>       
        <td><%= RSUserDays("PendingCount") %></td>
    </tr>
    <%RSUserDays.MoveNext 
    Loop
    %>
</table>

<%
RSUserDays.Close
RSUserList.MoveNext 
Loop

Set RSUserDays = Nothing

RSUserList.Close
Set RSUserList = Nothing

Set cmdUserDays = Nothing

FCConn.Close
Set FCConn = Nothing

Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader "Content-Disposition", "attachment; filename=excelTest.xls"
%>
</BODY>
</HTML>

运行正常但返回空结果。

2 个答案:

答案 0 :(得分:1)

这在Access中很难做到。但是,如果您假设某人每天都拨打电话,那么就有一个解决方案。我认为以下内容适用于Access:

SELECT d.dtmDate, Count(fc.ID) AS CallsClosed 
FROM (select distinct dtmDateClosed as dtmDate
      from tblFaultCall
      where dtmDateClosed BETWEEN  #"& FromMonth & "/" & FromDay & "/" & FromYear &"# and #"& ToMonth & "/" & ToDay & "/" & ToYear &"#
     ) as d left join
     tblFaultCall as fc
     on fc.dtmDateClosed = d.dtmDate and
        fc.strCallOwner = """ & strCallOwner & """
GROUP BY d.dtmDate
ORDER BY d.dtmDate;

编辑:

您可能需要将其表达为:

SELECT d.dtmDate, Count(fc.ID) AS CallsClosed 
FROM (select distinct dtmDateClosed as dtmDate
      from tblFaultCall
      where dtmDateClosed BETWEEN  #"& FromMonth & "/" & FromDay & "/" & FromYear &"# and #"& ToMonth & "/" & ToDay & "/" & ToYear &"#
     ) as d left join
     (select fc.*
      from tblFaultCall as fc
      where fc.strCallOwner = """ & strCallOwner & """
     ) as fc
     on fc.dtmDateClosed = d.dtmDate 
GROUP BY d.dtmDate
ORDER BY d.dtmDate;

我记得Access不喜欢连接中的多个条件。

答案 1 :(得分:1)

此查询为我们提供了&#34;已关闭&#34;计数

SELECT dtmDateClosed, COUNT(*) AS ClosedCount
FROM tblFaultCall
WHERE strCallOwner = 'Ben Hamilton'
GROUP BY dtmDateClosed

此查询为我们提供了&#34;待定&#34;计数

SELECT dtmDatePending, COUNT(*) AS PendingCount
FROM tblFaultCall
WHERE strCallOwner = 'Ben Hamilton'
GROUP BY dtmDatePending

列出所需范围内的所有日期以及&#34;已关闭&#34;计数将是

SELECT d.dtmDate, fc.ClosedCount
FROM
    (
        SELECT DISTINCT dtmDateOpen AS dtmDate
        FROM tblFaultCall 
        WHERE dtmDateOpen BETWEEN #2014-05-20# AND #2014-05-30#
    ) AS d
    LEFT JOIN
    (
        SELECT dtmDateClosed, COUNT(*) AS ClosedCount
        FROM tblFaultCall
        WHERE strCallOwner = 'Ben Hamilton'
        GROUP BY dtmDateClosed
    ) AS fc
        ON d.dtmDate = fc.dtmDateClosed

合并&#34;待定&#34;计数将是

SELECT d.dtmDate, fc.ClosedCount, fp.PendingCount
FROM
    (
        (
            SELECT DISTINCT dtmDateOpen AS dtmDate
            FROM tblFaultCall 
            WHERE dtmDateOpen BETWEEN #2014-05-20# AND #2014-05-30#
        ) AS d
        LEFT JOIN
        (
            SELECT dtmDateClosed, COUNT(*) AS ClosedCount
            FROM tblFaultCall
            WHERE strCallOwner = 'Ben Hamilton'
            GROUP BY dtmDateClosed
        ) AS fc
            ON d.dtmDate = fc.dtmDateClosed
    )
    LEFT JOIN
    (
        SELECT dtmDatePending, COUNT(*) AS PendingCount
        FROM tblFaultCall
        WHERE strCallOwner = 'Ben Hamilton'
        GROUP BY dtmDatePending
    ) AS fp
        ON d.dtmDate = fp.dtmDatePending

要在VBScript代码中包装它并使用正确的参数化查询

Option Explicit

Dim con  ' As ADODB.Connection
Dim cmd  ' As ADODB.Command
Dim rst  ' As ADODB.Recordset
Const adParamInput = 1
Const adDBDate = 133
const adVarWChar = 202

Set con = CreateObject("ADODB.Connection")
con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Public\Database1.accdb"

' test data
Const FromYear = 2014
Const FromMonth = 5
Const FromDay = 20
Const ToYear = 2014
Const ToMonth = 5
Const ToDay = 30
Const strCallOwner = "Ben Hamilton"

Set cmd = CreateObject("ADODB.Command")
cmd.ActiveConnection = con
cmd.CommandText = _
        "SELECT d.dtmDate, fc.ClosedCount, fp.PendingCount " & _
        "FROM " & _
            "( " & _
                "( " & _
                    "SELECT DISTINCT dtmDateOpen AS dtmDate " & _
                    "FROM tblFaultCall " & _
                    "WHERE dtmDateOpen BETWEEN ? AND ? " & _
                ") AS d " & _
                "LEFT JOIN " & _
                "( " & _
                    "SELECT dtmDateClosed, COUNT(*) AS ClosedCount " & _
                    "FROM tblFaultCall " & _
                    "WHERE strCallOwner = ? " & _
                    "GROUP BY dtmDateClosed " & _
                ") AS fc ON d.dtmDate = fc.dtmDateClosed " & _
            ") " & _
            "LEFT JOIN " & _
            "( " & _
                "SELECT dtmDatePending, COUNT(*) AS PendingCount " & _
                "FROM tblFaultCall " & _
                "WHERE strCallOwner = ? " & _
                "GROUP BY dtmDatePending " & _
            ") AS fp ON d.dtmDate = fp.dtmDatePending"
cmd.Parameters.Append cmd.CreateParameter("?", adDBDate, adParamInput, , DateSerial(FromYear, FromMonth, FromDay))
cmd.Parameters.Append cmd.CreateParameter("?", adDBDate, adParamInput, , DateSerial(ToYear, ToMonth, ToDay))
cmd.Parameters.Append cmd.CreateParameter("?", adVarWChar, adParamInput, 255, strCallOwner)
cmd.Parameters.Append cmd.CreateParameter("?", adVarWChar, adParamInput, 255, strCallOwner)

Set rst = cmd.Execute
Do Until rst.EOF
    WScript.Echo rst(0).Value & "  " & rst(1).Value & "  " & rst(2).Value
    rst.MoveNext
Loop

rst.Close
Set rst = Nothing
Set cmd = Nothing
con.Close
Set con = Nothing