我有一张看起来像这样的表:
+----------------+--------+
| EvidenceNumber | ID |
+----------------+--------+
| 001 | 8 |
| 001.A | 8 |
| 001.A.01 | 8 |
| 001.A.02 | 8 |
| 001.B | 8 |
| 001.C | 8 |
| 001.D | 8 |
| 001.E | 8 |
| 001.F | 8 |
| 001.G | 8 |
| 001.G.01 | 8 |
+----------------+--------+
如果 001 是一个包,它的内部是 001.A、001.B,依此类推到 001.G
在上面的输出中,001.A 是另一个包,该包包含 001.A.01 和 001.A.02。同样的事情可以用 001.G.01 看到。
此表中的每个条目要么是一个包,要么是一个项目。我只对计算每个 ID 的项目数量感兴趣。
由于 001.A.01 和 001.A.02 是我们最后看到的“001.A”,我们知道 A.01 和 A.02 是项目。
因为我们只看到 001.B 一次,那也是一个项目。
001.G 是包,而 001.G.01 是物品。
上面的输出显示了 8 个项目和 3 个包。
我觉得 Row_number 和 Partition 子句是完成这项工作的完美工具,但我找不到基于使用前一行值的子句进行分区的方法。
也许这样的事情在这里甚至没有必要,但我把它想象成:
{001} -- 变量 {001}.A -- 又见变量,显然 001 是一个包。创建新变量 {001.A} 并继续。
{001.A}.01——同样的事情。{001.A.01} - 唯一变量。这是最后一步。这是一个包,应该是第 1 行。
显然,下面的代码只是将每个项目的“ItemNum”设为 1,因为没有重复项。
SELECT
ROW_NUMBER() OVER(Partition BY EvidenceNumber ORDER BY EvidenceNumber) AS ItemNum,
EvidenceNumber,
ID
FROM EVIDENCE
WHERE ID = '18'
ORDER BY EvidenceNumber
+---------+----------------+--------+
| ItemNum | EvidenceNumber | ID |
+---------+----------------+--------+
| 1 | 001 | 8 |
| 1 | 001.A | 8 |
| 1 | 001.A.01 | 8 |
| 1 | 001.A.02 | 8 |
| 1 | 001.B | 8 |
| 1 | 001.C | 8 |
| 1 | 001.D | 8 |
| 1 | 001.E | 8 |
| 1 | 001.F | 8 |
| 1 | 001.G | 8 |
| 1 | 001.G.01 | 8 |
+---------+----------------+--------+
理想情况下,它只会对项目进行分区,因此在这种情况下:
+---------+----------------+----+
| ItemNum | EvidenceNumber | ID |
+---------+----------------+----+
| 0 | 001 | 8 |
| 0 | 001.A | 8 |
| 1 | 001.A.01 | 8 |
| 2 | 001.A.02 | 8 |
| 3 | 001.B | 8 |
| 4 | 001.C | 8 |
| 5 | 001.D | 8 |
| 6 | 001.E | 8 |
| 7 | 001.F | 8 |
| 0 | 001.G | 8 |
| 8 | 001.G.01 | 8 |
+---------+----------------+----+
我不认为单独的窗口函数是最好的方法。反而:
select t.*,
(case when exists (select 1
from evidence t2
where t2.caseid = t.caseid and
t2.EvidenceNumber like t.EvidenceNumber + '.%'
)
then 0 else 1
end) as is_item
from evidence t ;
然后使用另一个子查询总结这些:
select t.*,
sum(is_item) over (partition by caseid order by EvidenceNumber) as item_counter
from (select t.*,
(case when exists (select 1
from evidence t2
where t2.caseid = t.caseid and
t2.EvidenceNumber like t.EvidenceNumber + '.%'
)
then 0 else 1
end) as is_item
from evidence t
) t;
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句