Sql 带某些条件的序数
我有一个包含多个字段的视图,来自SQL Server 2016,如果满足某些条件,我喜欢输入一个序列号。 为了举例说明,考虑这个表: 表格:Sql 带某些条件的序数,sql,sql-server,sql-server-2016,Sql,Sql Server,Sql Server 2016,我有一个包含多个字段的视图,来自SQL Server 2016,如果满足某些条件,我喜欢输入一个序列号。 为了举例说明,考虑这个表: 表格: GLOBALID | SERVICE_GLOBALID | PHOTO_A_GLOBALID | PHOTO_B_GLOBALID ---------+------------------+------------------+----------------- EB8F9BE7 | 0CD85BE7 | 490794EC
GLOBALID | SERVICE_GLOBALID | PHOTO_A_GLOBALID | PHOTO_B_GLOBALID
---------+------------------+------------------+-----------------
EB8F9BE7 | 0CD85BE7 | 490794EC | 181C5426
EB8F9BE7 | 04405456 | C3A75999 | 5BA26B15
ECF5F7D1 | 8E8A63C2 | 1A225178 | NULL
ECF5F7D1 | 4EB18887 | 2139CF18 | C7B96E0E
一些细节:
可以重复(因为这是多个表中的一个视图,其中有一些GLOBALID
和交叉应用
)李>外部应用
从不重复李>服务\u GLOBALID
始终有一个值(从不重复)李>PHOTO\u A\u GLOBALID
可以有值,但有时为PHOTO_B_GLOBALID
(有值时从不重复)NULL
PHOTO\u a\u GLOBALID
和PHOTO\u B\u GLOBALID
设置一个序列号,但序列号必须使用视图中的两列。如果PHOTO\u B\u GLOBALID
为NULL
,则序列号不得递增
这是我想要的结果(请看第三行):
结果
GLOBALID | SERVICE_GLOBALID | PHOTO_A_GLOBALID | PHOTO_B_GLOBALID | SEQ_A | SEQ_B
---------+------------------+------------------+------------------+-------+------
EB8F9BE7 | 0CD85BE7 | 490794EC | 181C5426 | 1 | 2
EB8F9BE7 | 04405456 | C3A75999 | 5BA26B15 | 3 | 4
ECF5F7D1 | 8E8A63C2 | 1A225178 | NULL | 5 | NULL
ECF5F7D1 | 4EB18887 | 2139CF18 | C7B96E0E | 6 | 7
我试过使用ROW_NUMBER(),但我真的不知道如何使用两列来实现这一点。这有点棘手。我建议做一个累加和和一些额外的算术:
select t.*,
(sum(incThisRow) over (order by globalid, service_globalid) - incThisRow + 1
) as seq_A,
(case when photo_b_globalid is not null
then sum(incThisRow) over (order by globalid, service_globalid)
end) as seq_B
from (select t.*,
(case when PHOTO_B_GLOBALID is null then 1 else 2 end) as incThisRow
from t
) t;
你可以
- 将照片数据取消分割为两组(A、B)并合并它们
- 从B&Number中删除空照片的记录
- 连接回基本集以获取完整数据
With CTE AS (
SELECT GLOBALID, SERVICE_GLOBALID, PHOTO_A_GLOBALID, 'a' as RowID
union
SELECT GLOBALID, SERVICE_GLOBALID, PHOTO_B_GLOBALID, 'b'),
CTE2 as (
SELECT A.*, row_number() over order by (date) RN
FROM CTE A
WHERE PHOTO_B_GLOBALID is not null)
SELECT A.*, B.PHOTO_B_GLOBALID, A.RN as SEQ_A, B.RN as SEQ_B
FROM cte A
LEFT JOIN CTE2 B
on A.GLOBALID =B.GLOBALID
and A.SERVICE_GLOBALID = B.SERVICE_GLOBALID
and A.RowID = 'a'
and b.rowID = 'b'
试试这个:
雷克斯测试仪:
你可以这样试试
;WITH cte
AS (SELECT *, RowN = ROW_NUMBER() OVER (ORDER BY (SELECT NULL) )
FROM (SELECT GLOBALID, SERVICE_GLOBALID, PHOTO_A_GLOBALID
FROM yourglobal WHERE PHOTO_A_GLOBALID IS NOT NULL
UNION ALL
SELECT GLOBALID, SERVICE_GLOBALID, PHOTO_B_GLOBALID
FROM yourglobal WHERE PHOTO_B_GLOBALID IS NOT NULL) a)
SELECT
yg.*, c.RowN AS SEQ_A, cb.RowN AS SEQ_B
FROM yourglobal yg
LEFT JOIN cte c
ON yg.PHOTO_A_GLOBALID = c.PHOTO_A_GLOBALID
LEFT JOIN cte cb
ON yg.PHOTO_B_GLOBALID = cb.PHOTO_A_GLOBALID
正如其他答案所示,有不止一种方法可以做到这一点,但对我来说最直接的翻译是使用
count
函数进行计数:
select *,
case
when PHOTO_A_GLOBALID is not null
then count(PHOTO_A_GLOBALID)
over (order by DATE rows unbounded preceding)
+ count(PHOTO_B_GLOBALID)
over (order by DATE rows between unbounded preceding and 1 preceding)
end,
case
when PHOTO_B_GLOBALID is not null
then count(PHOTO_A_GLOBALID)
over (order by DATE rows unbounded preceding)
+ count(PHOTO_B_GLOBALID)
over (order by DATE rows unbounded preceding)
end
from t;
基本思想是计算当前行之前看到的所有PHOTO\u A\u GLOBALID
值,以及当前行之前看到的所有PHOTO\u B\u GLOBALID
值,只需稍加调整即可确保当前行的PHOTO\u B\u GLOBALID
值不会影响SEQ\u A
的计算值
现在,您可以通过知道PHOTO\u A\u GLOBALID
从来都不是NULL
来缩短这一点,但在我看来,这两列的逻辑相同,使得查询更容易理解
您还可以缩短此时间,因为当指定了
按顺序
时,前面无限制的行
是默认值,但您确实需要明确说明前面无限制的行和前面1位之间的行。分配的数字实际上在顺序上重要吗?我们怎么知道1,2组对3,4组?@xQbert我想我不明白你的问题。必须是一个序列,从1到无限,顺序与行的显示顺序相同(行的顺序是从order by date生成此视图的顺序)。您覆盖了它。结果是按日期排序的,因此应按该日期编号。edon't worked<代码>序列a
=1,序列b
=1,然后序列a
=3,序列b
=3,最后序列a
=5,序列b
=NULL@RobertoCorreia . . . 这似乎是seq_b
上的一个off-by-one错误。我认为这是解决这个问题的最简单的方法。不要这样做!在rextester上,将第3行的('EB8F9BE7'、'0CD85BE7'、'490794EC'、'181C5426')
更改为('EB8F9BE7'、'0CD85BE7'、'490794EC',null)
或在PHOTO__GLOBALID
上包含更多的您的解决方案有效!但是我不明白从哪里可以得到DATE
字段。视图上不存在此字段。我替换为globalid
,效果很好。@robertocoreia您对您的问题发表了评论“(行的顺序来自于生成此视图的日期顺序)”。如果DATE
不是用于订购的字段,请使用应该确定订单的实字段。stackoverflow上的示例比实视图(有26列)简单得多。我将尝试使用日期
!tks!(更新:使用日期工作正常
)
select *,
case
when PHOTO_A_GLOBALID is not null
then count(PHOTO_A_GLOBALID)
over (order by DATE rows unbounded preceding)
+ count(PHOTO_B_GLOBALID)
over (order by DATE rows between unbounded preceding and 1 preceding)
end,
case
when PHOTO_B_GLOBALID is not null
then count(PHOTO_A_GLOBALID)
over (order by DATE rows unbounded preceding)
+ count(PHOTO_B_GLOBALID)
over (order by DATE rows unbounded preceding)
end
from t;