创建SQL查询以按用户检索最新记录

时间:2013-05-22 19:26:52

标签: sql

我正在尝试让此查询仅返回仅针对特定用户的最新事务记录,目前我正在使用此查询,但是它混淆了我不需要的额外信息。

SELECT TOP 30 
    USER_NAME, 
    CONVERT(nvarchar(20), ACTIVITY_DATE_TIME, 20) AS DATE_TIME, 
    WORK_TYPE, Location, ITEM, Quantity 
FROM 
    TRANSACTION_HISTORY 
WHERE 
    USER_NAME in ('a_user','b_user','c_user','d_user','e_user')
ORDER BY 
    activity_date_time DESC

任何帮助将不胜感激

6 个答案:

答案 0 :(得分:1)

我相信用户希望在IN()子句中为每个用户返回最新的事务。

如果users是一个不同的表,我会在JOIN/CROSS APPLY表中的最新记录上建议TRANSACTION_HISTORY。但是因为它们在同一个表中,UNION怎么样?

SELECT TOP (1) *
FROM TRANSACTION_HISTORY
WHERE USER_NAME = 'a_user'
UNION ALL
SELECT TOP (1) *
FROM TRANSACTION_HISTORY
WHERE USER_NAME = 'b_user'
UNION ALL
SELECT TOP (1) *
FROM TRANSACTION_HISTORY
WHERE USER_NAME = 'c_user'
UNION ALL
SELECT TOP (1) *
FROM TRANSACTION_HISTORY
WHERE USER_NAME = 'd_user'
UNION ALL
SELECT TOP (1) *
FROM TRANSACTION_HISTORY
WHERE USER_NAME = 'e_user'
ORDER BY ACTIVITY_DATE_TIME DESC

此处ORDER BY将适用于整个查询,因为无法订购每个UNION个。

答案 1 :(得分:1)

假设mssql 2005+,您可以使用row_number按用户分区并按activity_date排序。然后你只选择用户的第一行......

SELECT
    *
FROM (
    SELECT
        USER_NAME, 
        CONVERT(nvarchar(20), ACTIVITY_DATE_TIME, 20) AS DATE_TIME, 
        WORK_TYPE, Location, ITEM, Quantity,
        RN = row_number() over(paritition by USER_NAME order by activity_date_time DESC)
    FROM 
        TRANSACTION_HISTORY 
    WHERE 
        USER_NAME in ('a_user','b_user','c_user','d_user','e_user')
) t
WHERE
    t.RN = 1 --only want the top history per user

如果表格非常大,可能最好使用apply,因为看起来你只需要一次为少数用户做这件事......

 SELECT 
        TTH.* 
    FROM 
        USER U 
        CROSS APPLY (
            SELECT TOP 1
                USER_NAME, 
                CONVERT(nvarchar(20), ACTIVITY_DATE_TIME, 20) AS DATE_TIME, 
                WORK_TYPE, Location, ITEM, Quantity
            FROM 
                TRANSACTION_HISTORY TH
            WHERE
                TH.USER_NAME = U.USER_NAME
            ORDER BY
                activity_date_time DESC
        ) TTH
    WHERE 
        U.USER_NAME in ('a_user','b_user','c_user','d_user','e_user')

答案 2 :(得分:1)

一种方法是使用CTE(公用表表达式),如果您使用的是SQL Server 2005及更高版本(在这方面您不够具体 - 其他RDBMS也具有CTE和窗口函数,如{{ 1}} - 那些不是SQL Server特定的功能。)

使用此CTE,您可以按照某些条件对数据进行分区 - 即ROW_NUMBER - 并为每个“分区”提供从1开始的所有行的SQL Server编号,按其他一些标准排序(如日期,在你的情况下)。

所以尝试这样的事情:

User_Name

在这里,我只选择每个“分区”的“第一个”条目(即每个;WITH MostRecentPerUser AS ( SELECT USER_NAME, CONVERT(nvarchar(20), ACTIVITY_DATE_TIME, 20) AS DATE_TIME, WORK_TYPE, Location, ITEM, Quantity, ROW_NUMBER() OVER(PARTITION BY USER_NAME ORDER BY CAST(ACTIVITY_DATE_TIME AS DATETIME) ) AS 'RowNum' FROM dbo.Transaction_History WHERE USER_NAME in ('a_user', 'b_user', 'c_user', 'd_user', 'e_user') ) SELECT USER_NAME, DATE_TIME, WORK_TYPE, Location, ITEM, Quantity FROM MostRecentPerUser WHERE RowNum = 1 ) - 按User_Name排序。

这会接近你想要的吗?

三个旁注:

  • 首先,如果您有日期 - 为什么不将其存储为Date_TimeDATETIME?它应该 - 认真!不要将日期存储为DATE - 永远不要!

  • 我会尽量避免使用所有大写标识符 - 这些会使您的代码难以阅读和理解。我们现在已经超越了ALL UPPERCASE终端 - 不是吗?

  • 另外:我建议尝试使用比NVARCHAR(20)更有意义且更具表现力的名称 - 首先,您有可能与DATE_TIME或{DATETIME之类的SQL Server关键字发生冲突{1}},其次 - 你应该努力让你的列名(和别名)真正表达它们所代表的内容 - DATESalesDateActivityDate好得多。< / p>

答案 3 :(得分:1)

这将为您提供每个用户的最新活动(假设ACTIVITY_DATE_TIME是实际的日期时间字段而不是varchar字段)

SELECT 
    USER_NAME, 
    max(ACTIVITY_DATE_TIME) as  ACTIVITY_DATE_TIME
FROM 
    TRANSACTION_HISTORY 
WHERE 
    USER_NAME in ('a_user','b_user','c_user','d_user','e_user')
GROUP BY user_name

如果您的用户具有相同日期时间的倍数(如果您实际上并未存储时间,那么您需要使用rownumber来获取一个。)

如果您还需要表中的其他列,请使用上述查询作为派生表:

SELECT <list the columns you need from theTRANSACTION_HISTORY table >
FROM TRANSACTION_HISTORY th
JOIN (
SELECT 
    USER_NAME, 
    max(ACTIVITY_DATE_TIME) as  ACTIVITY_DATE_TIME
FROM 
    TRANSACTION_HISTORY 
WHERE 
    USER_NAME in ('a_user','b_user','c_user','d_user','e_user')
GROUP BY user_name
) a  On th.USER_NAME = a.USER_NAME  and th. ACTIVITY_DATE_TIME = a. ACTIVITY_DATE_TIME

答案 4 :(得分:0)

从具有最新TRANSACTION_HISTORY

的表activity_date_time中检索记录的所有字段
SELECT * FROM TRANSACTION_HISTORY ORDER BY activity_date_time DESC LIMIT 1;

*更改为您要检索的字段。

显然,如果您只想检索USER_NAME列中有('a_user','b_user','c_user','d_user','e_user')个值的记录,请添加WHERE子句:

SELECT * 
FROM TRANSACTION_HISTORY 
WHERE USER_NAME in ('a_user','b_user','c_user','d_user','e_user')
ORDER BY activity_date_time DESC LIMIT 1;

答案 5 :(得分:0)

SELECT USER_NAME, convert(nvarchar(20),  
ACTIVITY_DATE_TIME, 20) as DATE_TIME, WORK_TYPE, 
Location, ITEM,Quantity 
FROM TRANSACTION_HISTORY WHERE USER_NAME in 
('a_user','b_user','c_user','d_user','e_user')
order by ACTIVITY_DATE_TIME desc LIMIT 1

这有帮助吗?