在SQL

时间:2017-02-09 08:41:39

标签: sql sql-server group-by

我有点陷入其中一个需要很少帮助的SQL查询中。

表结构如下:

表#1:PROD_ORDER

ID_PROD_ORDER(PK)
1001                   
1002              
1003   

表#2:JOB

ID_JOB | ID_PROD_ORDER(FK)|ID_ASSET | DT_START            | DT_END
1          1001               8       2016/11/22 05:45:50   2016/11/24 13:13:14
2          1001               8       some date             some date
3          1002               9       some date             some date
4          1002               9       some date             some date
5          1003               8       some date             some date
6          1001               8       some date             some date

表#3:Confirmation

ID_CONFIRMATION | ID_JOB | QT_CONF | QT_SCRAP

表#4:DOWNTIME

ID_DOWNTIME | DT_START | DT_END | ID_ORG_SUB_ASSET

现在要求是找到订单和

  • 订单的开始日期(来自JOB的DT_START的最小值)
  • 订单的结束日期(来自JOB的最大DT_END)
  • 所有工作的总和' QT_CONF
  • 所有工作的总和' QT_SCRAP
  • DOWNTIME表的停机时间,其中停机时间= DT_START的秒数差异 - DT_END

ID_ASSETStart DateEnd Date将作为参数传递。

我写了这个查询:

SELECT
    PO.ID_PROD_ORDER,
    J.ID_ORG_ASSET,
    SUM(C.QT_CONF) AS "QT_CONF",
    SUM(C.QT_SCRAP) AS "QT_SCRAP",
    MIN(J.DT_JOB_ST) AS "START_DATE",
    MAX(J.DT_JOB_ED) AS "END_DATE",
    (SELECT SUM(datediff(ss, D.DT_START, D.DT_END)) AS "DOWNTIMESECONDS"  
     FROM DOWNTIME D
     INNER JOIN SUB_ASSET SA ON D.ID_SUB_ASSET = SA.ID_SUB_ASSET
     WHERE SA.ID_ASSET = [Param.3] AND D.DT_START >= J.DT_JOB_ST 
       AND D.DT_END <= J.DT_JOB_ED) 
FROM
    PROD_ORDER PO
INNER JOIN 
    JOB J ON PO.ID_PROD_ORDER = J.ID_PROD_ORDER 
          AND J.DT_JOB_ST >= '[Param.1]' 
          AND J.DT_JOB_ED <= '[Param.2]'
LEFT OUTER JOIN 
    CONFIRMATION C ON C.ID_JOB = J.ID_JOB
WHERE
    J.ID_ASSET = [Param.3] 
GROUP BY 
    PO.ID_PROD_ORDER, J.ID_ASSET

查询引发错误:

  

JOB.DT_JOB_ST不能包含在选择列表中,因为它不用于聚合或GROUP BY

如果我将JOB.DT_JOB_STJOB.DT_JOB_ED放在GROUP BY中,则每个订单返回的行数超过1行,但每个订单只需要一行。

我该如何纠正?我只是困惑!!

谢谢!

2 个答案:

答案 0 :(得分:1)

我怀疑这里的问题是相关查询,它会尝试评估每一行 - 因为这包括DT_JOB_STDT_JOB_ED,它们需要这些成为该组的一部分。

另一种选择是重写为不需要相关查询,所以这样的事情对你有好处:

SELECT      PO.ID_PROD_ORDER,
            J.ID_ORG_ASSET,
            SUM(C.QT_CONF) AS [QT_CONF],
            SUM(C.QT_SCRAP) AS [QT_SCRAP],
            MIN(J.DT_JOB_ST) AS [START_DATE],
            MAX(J.DT_JOB_ED) AS [END_DATE],
            SUM(ISNULL(datediff(ss, D.DT_START, D.DT_END),0)) AS [DOWNTIMESECONDS]

FROM        PROD_ORDER PO

INNER JOIN  JOB J 
    ON      PO.ID_PROD_ORDER = J.ID_PROD_ORDER 
    AND     J.DT_JOB_ST >= '[Param.1]' 
    AND     J.DT_JOB_ED <= '[Param.2]'

LEFT JOIN   CONFIRMATION C
    ON      C.ID_JOB = J.ID_JOB

LEFT JOIN   DOWNTIME D
    INNER JOIN  SUB_ASSET SA
        ON      D.ID_SUB_ASSET = SA.ID_SUB_ASSET
        AND     SA.ID_ASSET = [Param.3]
    ON      D.DT_START >= J.DT_JOB_ST 
    AND     D.DT_END <= J.DT_JOB_ED

WHERE       J.ID_ASSET = [Param.3] 

GROUP BY    PO.ID_PROD_ORDER, J.ID_ORG_ASSET

(如果您愿意,CTE也可以起作用)

答案 1 :(得分:0)

以下查询工作:

Private Sub showQueryData()

Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim sqlStr As String

sqlStr = "SELECT COUNT(CalculatedField) AS TotalNumber FROM table1 AS tbl WHERE CalculatedField = 2"

Set db = CurrentDb
Set rs = db.OpenRecordset(sqlStr)

Dim result As String
result = rs!TotalNumber

End Sub