【问题标题】:SQL server - advanced groupingSQL 服务器 - 高级分组
【发布时间】:2012-12-20 11:40:13
【问题描述】:

我的桌子上有如下采购合同:

+------+-----------+------------+---------+------------+-----------+
| type | text      | date       | company | supplierID | name      |
+ -----+-----------+------------+---------+------------+-----------+
| 0    | None      | 2004-03-29 | 310     | 227234     | HRC INFRA |
| 0    | None      | 2007-09-30 | 310     | 227234     | HRC INFRA |
| 0    | None      | 2010-11-29 | 310     | 227234     | HRC INFRA |
| 2    | Strategic | 2011-01-01 | 310     | 227234     | HRC INFRA |
| 0    | None      | 2012-04-10 | 310     | 227234     | HRC INFRA |
+------+-----------+------------+---------+------------+-----------+

在此示例中,合同的前三行是相同的。所以我只想要第一个。 type = 2 的行是与给定供应商的采购合同的更改。我也想选择该行。 在最后一行,合约变回 0,所以我也想选择该行。

基本上我想选择第一行和合同类型发生变化的行。所以结果应该是这样的:

+------+-----------+------------+---------+------------+-----------+
| type | text      | date       | company | supplierID | name      |
+ -----+-----------+------------+---------+------------+-----------+
| 0    | None      | 2004-03-29 | 310     | 227234     | HRC INFRA |
| 2    | Strategic | 2011-01-01 | 310     | 227234     | HRC INFRA |
| 0    | None      | 2012-04-10 | 310     | 227234     | HRC INFRA |
+------+-----------+------------+---------+------------+-----------+

对我如何做到这一点有什么建议吗?

【问题讨论】:

  • 什么版本的 SQL Server?
  • 2008 R2标准版

标签: sql sql-server sql-server-2008-r2


【解决方案1】:
;WITH cte AS
 (
  SELECT ROW_NUMBER() OVER (ORDER BY date) AS Id,
         type, text, date, company, supplierId, name
  FROM your_table
  )
  SELECT c1.type, c1.text, c1.date, c1.company,
         c1.supplierId, c1.name
  FROM cte c1 LEFT JOIN cte c2 ON c1.id = c2.id + 1
  WHERE c2.text IS NULL OR c1.text != c2.text

SQLFiddle上的演示

【讨论】:

    【解决方案2】:

    我面前没有 SQL 服务器来测试它,所以我现在不打算尝试实际的解决方案,但仅供参考,您需要的东西很少:

    1) 一种确保记录正确排序的方法。我在这里看不到任何类型的 id,这意味着您无法保证它们会按该顺序出现。我假设有一个,所以请确保您按它订购

    2) 无论索引是什么,您都需要在表上对其自身进行外部连接,但不是“table1.index = table2.index”,而是看起来像“table1.index = table2.index + 1” .如果您的索引不是连续的,那么以这种方式连接它们会比这更复杂。

    3) 在 where 子句中,您将指定类似

    的内容
    where table1.type <> table2.type
    

    这将使您最容易到达那里。不过,这不会获得第一条记录,因为在第一条记录之前没有记录可以比较,因此您需要添加 OR 来弥补这一点。而且我假设该类型没有 NULL 值。

    很抱歉,我无法为实际实施提供更多帮助,但也许其他人会尽快处理。

    【讨论】:

      【解决方案3】:

      可能是你想要的。假设你没有类型

      SELECT * 
      FROM [TABLE] as ot where ot.type <> 
      (select top 1 coalesce(it.type, -1) from [TABLE] as it where it.date < ot.date order by it.date desc)
      

      另外,请注意不要让舒尔表订购,因为我没有看到 PK。

      【讨论】:

      • 很好的查询。只需 UNION 你的结果与 SELECT TOP 1 * FROM [Table] ,你就会得到这个问题所要求的结果。在最外面的选择中按日期排序也是一个不错的补充。
      • 是的,你是对的。我没有带工具的 atm 和 cba 去 sqlfiddle 构建表。 +1 指出缺陷。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多