Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
连续数分组的SQL查询_Sql_Sql Server_Tsql_Group By - Fatal编程技术网

连续数分组的SQL查询

连续数分组的SQL查询,sql,sql-server,tsql,group-by,Sql,Sql Server,Tsql,Group By,假设我有下表: | ... | orderId | serialNumber | type | ... | |-----|---------|--------------|---------------|-----| | ... | 1 | 01 | someType | ... | | ... | 1 | 02 | someType | ... | | ... | 1 | 03

假设我有下表:

| ... | orderId | serialNumber | type          | ... |
|-----|---------|--------------|---------------|-----|
| ... | 1       | 01           | someType      | ... |
| ... | 1       | 02           | someType      | ... |
| ... | 1       | 03           | someOtherType | ... |
| ... | 1       | 04           | someOtherType | ... |
| ... | 1       | 05           | someType      | ... |
| ... | 1       | 06           | someType      | ... |
| ... | 2       | 07           | someType      | ... |
| ... | 2       | 08           | someType      | ... |
我希望我的查询生成以下结果:

| orderId | count | min | max | type          |
|---------|-------|-----|-----|---------------|
| 1       | 2     |  01 | 02  | someType      |
| 1       | 2     |  03 | 04  | someOtherType |
| 1       | 2     |  05 | 06  | someType      |
| 2       | 4     |  07 | 08  | someType      |
我需要按类型和医嘱ID分组。当serialNumber未运行时,应创建一个新条目

这是我当前的查询:

SELECT
 orderId,
 count(*) AS count,
 min(serialNumber) AS min,
 max(serialNumber) AS max,
 type
FROM tblMyTable
group by type, orderId
order by orderId
但它造成的结果是错误的:

| orderId | count | min | max | type          |
|---------|-------|-----|-----|---------------|
| 1       | 4     |  01 | 06  | someType      |  <-- this should be 2 entries
| 1       | 2     |  03 | 04  | someOtherType |
| 2       | 2     |  07 | 08  | someType      |

这可能需要一些运行,但只是一个开始

with cte as (
      SELECT *, row_number() over (partition by type, orderId order by serialNumber) as rn
      FROM Table1
)
SELECT *
FROM cte c1
LEFT JOIN cte c2
  ON c1.orderId =  c2.orderId
 AND c1.type = c2.type
 AND c1.rn = c2.rn-1
 AND c1.rn % 2  = 1
输出

+----+---------+--------------+---------------+----+---------+--------------+---------------+------+
|    | orderId | serialNumber |     type      | rn | orderId | serialNumber |     type      |  rn  |
+----+---------+--------------+---------------+----+---------+--------------+---------------+------+
|  1 |       1 |            3 | someOtherType |  1 | 1       | 4            | someOtherType | 2    |
|  2 |       1 |            4 | someOtherType |  2 | NULL    | NULL         | NULL          | NULL |
|  3 |       1 |            1 | someType      |  1 | 1       | 2            | someType      | 2    |
|  4 |       1 |            2 | someType      |  2 | NULL    | NULL         | NULL          | NULL |
|  5 |       1 |            5 | someType      |  3 | 1       | 6            | someType      | 4    |
|  6 |       1 |            6 | someType      |  4 | NULL    | NULL         | NULL          | NULL |
|  7 |       2 |            7 | someType      |  1 | 2       | 8            | someType      | 2    |
|  8 |       2 |            8 | someType      |  2 | NULL    | NULL         | NULL          | NULL |
+----+---------+--------------+---------------+----+---------+--------------+---------------+------+

这里还有另一个选项,假设序列由
[serialNumber]
决定

这通常称为缺口和孤岛问题

示例

;with cte as (
    Select *
          ,Grp = sum(Flg) over (order by [serialNumber])
        From (
              Select *
                    ,Flg = case when concat(orderid,type)<> lag(concat(orderid,type),1) over (Order by [serialNumber]) then 1 else 0 end
               From  YourTable
             ) A
)
Select [orderid]
      ,[count] = count(*)
      ,[min]   = min ([serialNumber])
      ,[max]   = max ([serialNumber])
      ,[type]  = max([type])
 From  cte
 Group by [orderid],Grp

这是一个缺口和孤岛问题,但我会使用行号差异的方法:

select orderid, count(*), min(serialNumber), max(serialNumber), type
from (select t.*,
             row_number() over (partition by orderid order by serialnumber) as seqnum,
             row_number() over (partition by orderid, type order by serialnumber) as seqnum_type
      from t
     ) t
group by orderid, type, (seqnum - seqnum_type)
order by orderid, min(serialNumber);
您的
serialnumber
看起来像一个字符串,但它有数值。如果您可以信任它的顺序,您甚至不需要两个行号值:

select orderid, count(*), min(serialNumber), max(serialNumber), type
from (select t.*,
             row_number() over (partition by orderid, type order by serialnumber) as seqnum_type
      from t
     ) t
group by orderid, type, (serialnumber - seqnum_type)
order by orderid, min(serialNumber);

这样做的原因有点难以解释,但如果您运行子查询,这是很明显的。您将看到行号之间的差异如何标识您想要标识的组。

我猜您对SQL分组的解释有点错误。分组是不考虑记录顺序的。它聚合了所有具有相同分组字段值的记录(在您的案例中是orderId和type)。要将一行拆分为两行,您应该找到一些使这行不同的字段。您的rdbms是什么?Sql Server、postgres、oracle?MS Transact-Sqlall类型成对出现?不,也可以出现单个类型。我已经用这些信息更新了我的问题。更干净了。。。我刚把旗子的方法卡在我的小脑袋里+1
select orderid, count(*), min(serialNumber), max(serialNumber), type
from (select t.*,
             row_number() over (partition by orderid order by serialnumber) as seqnum,
             row_number() over (partition by orderid, type order by serialnumber) as seqnum_type
      from t
     ) t
group by orderid, type, (seqnum - seqnum_type)
order by orderid, min(serialNumber);
select orderid, count(*), min(serialNumber), max(serialNumber), type
from (select t.*,
             row_number() over (partition by orderid, type order by serialnumber) as seqnum_type
      from t
     ) t
group by orderid, type, (serialnumber - seqnum_type)
order by orderid, min(serialNumber);