带有额外列的SQL查询组

时间:2015-10-22 11:15:20

标签: sql sql-server tsql

我一直在尝试创建一个sql查询,该查询返回给定日期每个用户的最新记录。

Select dbfirst, dblast, max(dbdate) as MaxDate 
from table 
where (DATEPART(yy, dbdate) = 2015 
  AND DATEPART(mm, dbdate) = 10 
  AND DATEPART(dd, dbdate) = 22) 
group by dbfirst, dblast

我得到的结果是针对在指定日期登录的用户,即

╔═════════╦════════╦════════════════════════╗
║ dbfirst ║ dblast ║   MaxDate              ║
╠═════════╬════════╬════════════════════════╣
║ user    ║     10 ║ 20151022 13:13:09.000  ║
║ user    ║     11 ║ 20151022 10:18:50.000  ║
╚═════════╩════════╩════════════════════════╝

这只返回最新用户的一条记录。

我还需要能够显示列' dbflow'在结果中是varchar" In"或" Out"但是当我这样做的时候。

Select  dbfirst, dblast, dbflow, max(dbdate) as MaxDate from [Inventory].[dbo].[pr_dbs] where (DATEPART(yy, dbdate) = 2015 AND DATEPART(mm, dbdate) = 10 AND DATEPART(dd, dbdate) = 22) group by dbfirst, dblast, dbflow

它返回最新的In和Out,我只需要最新的记录,无论dbflow如何。

╔═════════╦════════╦════════╦═════════════════════════╗
║ dbfirst ║ dblast ║ dbflow ║ MaxDate                 ║
╠═════════╬════════╬════════╬═════════════════════════╣
║ user    ║ 10     ║ In     ║ 2015-10-22 13:13:09.000 ║
║ user    ║ 11     ║ In     ║ 2015-10-22 10:18:50.000 ║
║ user    ║ 10     ║ Out    ║ 2015-10-22 12:13:09.000 ║
║ user    ║ 11     ║ Out    ║ 2015-10-22 9:18:50.000  ║
╚═════════╩════════╩════════╩═════════════════════════╝

提前感谢您的帮助或建议。

4 个答案:

答案 0 :(得分:3)

根据官方 Microsoft培训套件考试70-461 (SQL Server),您有3个问题的解决方法(如果您知道不能有多个不同的dbflow)每个 distinct(dbfirst,dblast)):

  1. 只需将其添加到GROUP BY子句

  2. 即可
  3. 第二个选项是将类似MAX的聚合函数应用于列。

  4. 第三个选项是首先对[pr_dbs]表中的行进行分组和聚合,根据分组查询定义表表达式,然后将表表达式与[pr_dbs]原始表连接以获取最后一栏

  5. WITH CTE AS (
    SELECT dbfirst, dblast, max(dbdate) as MaxDate 
         FROM [Inventory].[dbo].[pr_dbs]
         WHERE (DATEPART(yy, dbdate) = 2015 
         AND DATEPART(mm, dbdate) = 10 
         AND DATEPART(dd, dbdate) = 22) 
         GROUP BY dbfirst, dblast
     )
     SELECT CTE.*, D.dbflow
     FROM [Inventory].[dbo].[pr_dbs] AS D
          INNER JOIN CTE
          ON D.dblast = CTE.dblast
          AND D.dbfirst = CTE.dbfirst;
    
      

    SQL Server通常会优化第三种解决方案   第一。第一种解决方案可能更可取,因为它涉及很多   更少的代码。

    修改

    当您解决问题时,它是否满足您的需求:

    SELECT table.dbfirst, table.dblast, table.MaxDate, table.dbflow
    FROM table 
        INNER JOIN 
        (
            SELECT dbfirst, dblast, max(dbdate) as MaxDate 
            FROM table
            WHERE (DATEPART(yy, dbdate) = 2015 
            AND DATEPART(mm, dbdate) = 10 
            AND DATEPART(dd, dbdate) = 22)
            GROUP BY dbfirst, dblast
        ) AS T
        ON table.dbfirst = T.dbfirst
        AND table.dblast = T.dblast
        AND table.dbdate = T.MaxDate
    

答案 1 :(得分:1)

您是否想过使用窗口函数?这将是您的查询的示例:

SELECT DISTINCT dbflow
    , dbfirst
    , dblast
    , MAX(dbdate) OVER (PARTITION BY dbfirst, dblast) AS MaxDate
FROM [Inventory].[dbo].[pr_dbs]
WHERE DATEPART(yy, dbdate) = 2015
    AND DATEPART(mm, dbdate) = 10
    AND DATEPART(dd, dbdate) = 22;

但是,我不确定这是否是正确的逻辑。

答案 2 :(得分:0)

请勿使用日期部分进行比较。函数的使用通常会排除索引的使用。因此,您查询的一种可能性是:

Select dbfirst, dblast, max(dbdate) as MaxDate, AVG(dbflow)
from table 
where dbdate >= '2015-10-22' and dbdate < '2015-10-23'
group by dbfirst, dblast;

如果您想要日期的最后一个流程,那么请使用没有聚合的窗口函数:

Select dbfirst, dblast, dbdate as MaxDate, dbflow
from (select t.*,
             row_number() over (order by dbdate desc) as seqnum
      from table t
      where dbdate >= '2015-10-22' and dbdate < '2015-10-23'
     ) t
where seqnum = 1;

这两个查询都可以利用table(dbdate)上的索引,而您的版本却无法使用该索引。

答案 3 :(得分:-1)

您为dbfirstdblast显示一个结果行,并希望为其显示dbflow。但是哪一个?每dbfirstdblast有几条记录,这就是为什么您无法显示dbdate,而是决定一个日期,即max(dbdate)

与日期一样,您必须决定显示哪个dbflow并相应地使用MAX,MIN,AVG或其他任何内容。