sql - 尝试在不使用 UNION 的情况下简化 SQL 查询

标签 sql sql-server tsql

我很不擅长解释,所以让我试着阐述一下我的问题。我有一个类似于以下内容的表格:

 Source    Value    User
========  =======  ======
  old1       1      Phil
  new        2      Phil
  old2       3      Phil
  new        4      Phil
  old1       1      Mike
  old2       2      Mike
  new        1      Jeff
  new        2      Jeff

我需要做的是创建一个查询,根据源和值获取用户的值。它应该遵循以下规则:

For every user, get the highest value. However, disregard the 'new' source if either 'old1' or 'old2' exists for that user.

因此,根据这些规则,我的查询应从该表返回以下内容:

 Value    User
=======  ======
   3      Phil
   2      Mike
   2      Jeff

我提出了一个与所要求的内容接近的查询:

SELECT      MAX([Value]), [User]
FROM
(
    SELECT  CASE [Source]
                WHEN 'old1' THEN 1
                WHEN 'old2' THEN 1
                WHEN 'new'  THEN 2
            END                 AS [SourcePriority],
            [Value],
            [User]
    FROM    #UserValues
) MainPriority
WHERE       [SourcePriority] = 1
GROUP BY    [User]
UNION
SELECT      MAX([Value]), [User]
FROM
(
    SELECT  CASE [Source]
                WHEN 'old1' THEN 1
                WHEN 'old2' THEN 1
                WHEN 'new'  THEN 2
            END                 AS [SourcePriority],
            [Value],
            [User]
    FROM    #UserValues
) SecondaryPriority
WHERE       [SourcePriority] = 2
GROUP BY    [User]

但是这会返回以下结果:

 Value    User
=======  ======
   3      Phil
   4      Phil
   2      Mike
   2      Jeff

显然,Phil=4 的额外值是不需要的。我应该如何尝试修复此查询?我也知道这是一个相当复杂的解决方案,并且通过正确使用聚合可能可以更轻松地解决它,但是我对聚合还不太熟悉,这导致我诉诸联合。本质上,我正在寻求帮助来创建尽可能简洁的解决方案。

如果有人想自己填充表来尝试一下,这里是 SQL 代码:

CREATE TABLE #UserValues
(
    [Source] VARCHAR(10),
    [Value]  INT,
    [User]   VARCHAR(10)
)
INSERT INTO #UserValues VALUES
('old1', 1, 'Phil'),
('new',  2, 'Phil'),
('old2', 3, 'Phil'),
('new',  4, 'Phil'),
('old1', 1, 'Mike'),
('old2', 2, 'Mike'),
('new',  1, 'Jeff'),
('new',  2, 'Jeff')

最佳答案

您可以相当轻松地解决这个问题,而无需借助窗口函数。在这种情况下,您需要最大值,其中((不是新的)OR(没有 old1 或 old2 条目))。

下面是一个可以正确处理示例数据的查询:

SELECT
    MAX(U1.[Value]) as 'Value'
    ,U1.[User]
FROM
    #UserValues U1
WHERE
    U1.[Source] <> 'new' 
    OR NOT EXISTS (SELECT * FROM #UserValues U2 WHERE U2.[User] = U1.[User] AND U2.[Source] IN ('old1','old2'))
GROUP BY U1.[User]

关于sql - 尝试在不使用 UNION 的情况下简化 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53398354/

相关文章:

sql - 索引二进制列会提高 SQL WHERE BETWEEN 语句的性能吗?

android - 在android中使用rawQuery查询数据库

sql - 如何限制 Ingres 中任意查询的结果集大小?

sql - 如何组合 2 位列

c# - DataGridView - 如何仅为单个列设置货币格式

sql - 避免在 SQL 中进行两步插入

python - 如何在SQL中获取最后创建的ID

sql-server - SSAS 测量组 EstimatedSize EstimatedRows

c# - 即使提供了参数,过程仍需要参数

sql - TSQL 使用子字符串替换也会替换字符串的其他部分