【问题标题】:SELECT TOP with multiple UNION and with ORDER BY带有多个 UNION 和 ORDER BY 的 SELECT TOP
【发布时间】:2017-05-09 06:30:21
【问题描述】:

我想从 SQL Server 的数据库中选择最新的记录。如果只选择一项,则最终输出如下:

SELECT TOP(10) * from dbo.Eventos WHERE Tipo LIKE '%OS%' AND Distrito LIKE '%' 

+ 总是加在最后:

ORDER BY Data DESC

注意Distrito LIKE '%' 必须保留,因为它有时会以编程方式更改为 % 以外的其他内容。

如果选择了更多项目,则查询将获得一个UNION以编程方式为每个项目添加。最后,一如既往地添加ORDER BY。检查所有 4 项的示例:

SELECT TOP(10) * from dbo.Eventos WHERE Tipo LIKE '%OS%' AND Distrito LIKE '%' 
UNION ALL SELECT TOP(10) * from dbo.Eventos WHERE Tipo LIKE '%Rad%' AND Distrito LIKE '%' 
UNION ALL SELECT TOP(10) * from dbo.Eventos WHERE Tipo LIKE '%Aci%' AND Distrito LIKE '%'
UNION ALL SELECT TOP(10) * from dbo.Eventos WHERE Tipo LIKE '%Out%' AND Distrito LIKE '%' 
ORDER BY Data DESC

但这给了我OLDEST 10 个结果,每个WHERE 子句排序BY Data DESC

我怎样才能获得每个项目的NEWEST X 个结果 (WHERE)?

【问题讨论】:

  • 这看起来真的像 SQL server 而不是 mySQL。你确定你的标签是正确的吗?

标签: sql-server select sql-order-by union union-all


【解决方案1】:

如果我理解正确,您想要每个提示的 10 个最新事件,例如 os、rad、aci、out。您可以通过查看数据来确定最新的数据(我假设这是一个日期字段)我们可以通过在不使用所有联合的情况下使用 Tipo 的 ROW_NUMBER 分区来完成此操作。但是由于我们有tipo的通配符,我们需要将它们定义到同一个集合中;这可以通过窗口函数中的 case 语句来完成。

我假设 Distrito 在填充时对每个 Tipo 具有相同的值。

WITH CTE AS (
    SELECT E.*, Row_number() over (partition by 
      CASE WHEN Tipo LIKE '%OS%' then 'OS' 
           WHEN Tipo like '%Rad%' then 'Rad'
           WHEN Tipo LIKE '%Aci%' then 'ACI'
           WHEN tipo LIKE '%Out%' then 'OUT' end order by data Desc) RN
    FROM dbo.Eventos E 
    WHERE (Tipo LIKE '%OS%' OR Tipo LIKE '%Rad%' OR Tipo LIKE '%Aci%' OR Tipo LIKE '%Out%') 
      AND Distrito like '%')
SELECT * 
FROM  cte 
WHERE RN <=10;

我们使用公用表表达式 (CTE),因为我们需要先为行号生成结果,然后才能对其进行限制。由于 row_number 将针对每个不同的 Tipo 重新启动,我们只需要让那些

或者只是建立在你所做的基础上......

SELECT * FROM (
  SELECT * FROM 
  (SELECT TOP(10) * from dbo.Eventos WHERE Tipo LIKE '%OS%' AND Distrito LIKE '%' ORDER BY DATA desc) A 
  UNION ALL
  SELECT * FROM  
  (SELECT TOP(10) * from dbo.Eventos WHERE Tipo LIKE '%Rad%' AND Distrito LIKE '%' ORDER BY DATA DESC) B
  UNION ALL 
  SELECT * FROM 
  (SELECT TOP(10) * from dbo.Eventos WHERE Tipo LIKE '%Aci%' AND Distrito LIKE '%' ORDER BY DATA DESC) C
  UNION ALL 
  SELECT * FROM 
  (SELECT TOP(10) * from dbo.Eventos WHERE Tipo LIKE '%Out%' AND Distrito LIKE '%' ORDER BY Data DESC) D
) E
ORDER BY DATA DESC;

您需要子查询有自己的顺序,以便为每个 Tipo 分组获得正确的前 10 名。要实现这一点,您需要每个查询充当内联视图并在联合发生之前完全实现(实际生成数据)。

【讨论】:

  • 你的第一个解决方案给了我Incorrect syntax near 'Row_number'。您的第二个解决方案也不起作用(3 Incorrect syntax near the keyword 'ORDER' 错误,第 5、7 和 9 行),但似乎更多是我需要的(不要忘记以编程方式添加额外的 SELECT (UNION)。我已经更新了我的问题澄清。
  • 第一个在 E.* 和 row_number 之间缺少逗号。第二个需要添加多个选择和一些()。通过第二个解决方案中的所有重复,您可以看到为什么我发现第一个更优雅。
  • 第一个以编程方式实现不如第二个解决方案简单,它完全按照我的意愿工作。
猜你喜欢
  • 1970-01-01
  • 2016-11-22
  • 1970-01-01
  • 1970-01-01
  • 2011-09-11
  • 1970-01-01
  • 2010-10-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多