Sql 带某些条件的序数

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

我有一个包含多个字段的视图,来自SQL Server 2016,如果满足某些条件,我喜欢输入一个序列号。 为了举例说明,考虑这个表:

表格

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;