使用动态创建的相等字段加入2个查询

时间:2012-09-20 18:53:55

标签: sql sql-server-2008 join dynamically-generated

我有一张桌子,我想创建一些图表。 基本上我需要知道我在10分钟的间隔内有多少个寄存器,以及它们中有多少已经过处理。通过这两个查询,我得到了我需要的信息,但我只需要1个结果表中的2个。

第一次查询

SELECT  
    (
        CAST(DATEPART(HOUR, m.Ocr_DataHora) AS NVARCHAR) +
        ':' +
        CAST((DATEPART(MINUTE, m.Ocr_DataHora) % 6) AS NVARCHAR) +
        '0'         
    )                                       AS Hora,
    COUNT(*)                                AS Movimentações
FROM
    Integracao m
WHERE
        m.Ocr_DataHora      >=  '2012-09-17 00:00:00.000'
    AND m.Ocr_DataHora      <   '2012-09-18 00:00:00.000'
GROUP BY        
    DATEPART(HOUR, m.Ocr_DataHora),
    (DATEPART(MINUTE, m.Ocr_DataHora) % 6)
ORDER BY    
    DATEPART(HOUR, m.Ocr_DataHora),
    (DATEPART(MINUTE, m.Ocr_DataHora) % 6)

第二次查询

SELECT  
    (
        CAST(DATEPART(HOUR, s.Ocr_DataHora) AS NVARCHAR) +
        ':' +
        CAST((DATEPART(MINUTE, s.Ocr_DataHora) % 6) AS NVARCHAR) +
        '0'         
    )                                       AS Hora,
    COUNT(*)                                AS Sucesso
FROM
    Integracao s
WHERE
        s.Veiculo_Modelo    <>  ''
    AND s.Ocr_DataHora      >=  '2012-09-17 00:00:00.000'
    AND s.Ocr_DataHora      <   '2012-09-18 00:00:00.000'
GROUP BY        
    DATEPART(HOUR, s.Ocr_DataHora),
    (DATEPART(MINUTE, s.Ocr_DataHora) % 6)

如果我的公共字段是动态生成的,我如何加入它们?

3 个答案:

答案 0 :(得分:1)

正如其他人已经告诉过你的那样,你可以使用两个查询作为派生表(子选择),并使用每个Hora列加入它们。如果在查询中计算列无关紧要,在连接条件下使用它是完全合法的。

但是,我认为通过计算单个查询中的两个计数(即没有子查询),可以更有效地获得相同的结果。以下是您可以这样做的方法:

SELECT  
    (
        CAST(DATEPART(HOUR, m.Ocr_DataHora) AS NVARCHAR) +
        ':' +
        CAST((DATEPART(MINUTE, m.Ocr_DataHora) % 6) AS NVARCHAR) +
        '0'         
    )                                                  AS Hora,
    COUNT(*)                                           AS Movimentações,
    COUNT(CASE WHEN s.Veiculo_Modelo <> '' THEN 1 END) AS Sucesso
FROM
    Integracao m
WHERE
        m.Ocr_DataHora      >=  '2012-09-17 00:00:00.000'
    AND m.Ocr_DataHora      <   '2012-09-18 00:00:00.000'
GROUP BY        
    DATEPART(HOUR, m.Ocr_DataHora),
    (DATEPART(MINUTE, m.Ocr_DataHora) % 6)
ORDER BY    
    DATEPART(HOUR, m.Ocr_DataHora),
    (DATEPART(MINUTE, m.Ocr_DataHora) % 6)

如您所见,查询不会过滤s.Veiculo_Modelo <> ''上的行。但是,在计算Sucesso列的行时会使用该条件。第二个COUNT的参数是CASE表达式。如果满足指定的条件,则返回一个值(任意选择为1,但可以是任何实际值),否则为NULL。由于COUNT省略了空值,因此结果将与计算和返回Sucesso的专用查询相同。

答案 1 :(得分:0)

我假设您希望输出如下:

Hora | Movimentações | Sucesso

您可以使用WITH语句将两个SQL查询视为表,如下所示:

WITH 
firstQuery(Hora, Movimentações) AS (<first query definition with out ORDER BY >),
secondQuery(Hora, Sucesso) AS (<second query definition with out ORDER BY >)
SELECT
     f.Hora, f.Movimentações , s.Sucesso
FROM 
    firstQuery f
    JOIN secondQuery s
    ON f.Hora = s.Hora

答案 2 :(得分:0)

您应该可以通过将它们放在from子句中的子查询中来完成此操作。我指的方式有以下形式:

Select A.Hora,A.Movimentações,B.Sucesso
From (*First Query*) as A
inner join (*Second Query*) as B on A.Hora = B.Hora

最终结果是:

Select A.Hora,A.Movimentações,B.Sucesso
From (SELECT  
    (
        CAST(DATEPART(HOUR, m.Ocr_DataHora) AS NVARCHAR) +
        ':' +
        CAST((DATEPART(MINUTE, m.Ocr_DataHora) % 6) AS NVARCHAR) +
        '0'         
    )                                       AS Hora,
    COUNT(*)                                AS Movimentações
FROM
    Integracao m
WHERE
        m.Ocr_DataHora      >=  '2012-09-17 00:00:00.000'
    AND m.Ocr_DataHora      <   '2012-09-18 00:00:00.000'
GROUP BY        
    DATEPART(HOUR, m.Ocr_DataHora),
    (DATEPART(MINUTE, m.Ocr_DataHora) % 6)
ORDER BY    
    DATEPART(HOUR, m.Ocr_DataHora),
    (DATEPART(MINUTE, m.Ocr_DataHora) % 6)) As A
inner join (SELECT  
    (
        CAST(DATEPART(HOUR, s.Ocr_DataHora) AS NVARCHAR) +
        ':' +
        CAST((DATEPART(MINUTE, s.Ocr_DataHora) % 6) AS NVARCHAR) +
        '0'         
    )                                       AS Hora,
    COUNT(*)                                AS Sucesso
FROM
    Integracao s
WHERE
        s.Veiculo_Modelo    <>  ''
    AND s.Ocr_DataHora      >=  '2012-09-17 00:00:00.000'
    AND s.Ocr_DataHora      <   '2012-09-18 00:00:00.000'
GROUP BY        
    DATEPART(HOUR, s.Ocr_DataHora),
    (DATEPART(MINUTE, s.Ocr_DataHora) % 6)) As B on B.Hora = A.Hora