【问题标题】:Invert The Sequence反转序列
【发布时间】:2017-11-06 15:11:49
【问题描述】:

这是我在一次采访中被问到的一个问题。对于这样的表(可能有数百或数千条此类记录)

什么是恢复 Seq 的最佳方法,这样 A 将是 seq 4,B 将是 seq 1,如下所示:

我给了他以下查询(我使用 CTE 只是为了创建示例场景。在原始情况下它是一个表):

WITH CTE
AS
(
    SELECT
        Seq = 1,Nm = 'A'
    UNION
    SELECT
        Seq = 2,Nm = 'A'
    UNION
    SELECT
        Seq = 3,Nm = 'B'
    UNION
    SELECT
        Seq = 4,Nm = 'B'
)
SELECT
    Seq = ROW_NUMBER() OVER(ORDER BY Seq DESC),
    Seq,
    Nm
    FROM CTE;

是否有任何替代的动态查询以更有效的方式实现相同的目标?

【问题讨论】:

  • 一个非常人为的问题对我来说似乎很合理。
  • UNION 更改为UNION ALL,这是此查询中唯一可以进行的改进。或者,如果您能解释您最初的要求,我们可以看看是否有更好的方法。
  • 别为工会操心了。我写这个只是为了检查场景。实际输入将是具有相同结构的表
  • JayasuryaSatheesh 我们打扰是因为这很重要,所以请听从建议。正如@Pரதீப் 所说,除了检查索引之外,您无法再改进该查询
  • 还有另一种产生所需输出的方法。您可以使用ABS(Seq - sqq - 1),其中sqqSeq 列中的最大值,但此解决方案需要以某种方式从Seq 获得最大值并在Seq 列上使用函数,这可以防止使用索引。跨度>

标签: sql sql-server sql-server-2008 sql-server-2012


【解决方案1】:

怎么样?

select seq, (case when nm = 'B' then 'A' else 'B' end) as nm
from t;

【讨论】:

  • 工作,但我认为这不是面试问题的精神。
  • 我不认为这更有效,因为如果有另一个值,那么你必须再写一个案例。我想要的是一个像问题中的动态查询
  • @JayasuryaSatheesh 他只是回答你的问题,而不是假设的问题。由你来解释要求。
  • @JayasuryaSatheesh 。 . .只能回答被问到的问题。这个问题似乎很简单。我不会问这样的问题,但我绝对不会少考虑使用 row_number() 的答案,除非问题是专门针对最有效的方法。
  • 我的错误我忘了说这只是一个示例。我会更新我的问题@GordonLinoff
【解决方案2】:

如果我将表的计数保存到声明的变量中,那么我可以进行子查询以获取反转的第二列。 SQL Server 执行计划指示批处理成本低于 ROWNUMBER()。

DECLARE @tablename TABLE(seq int PRIMARY KEY, Nm char(1))
INSERT INTO @tablename VALUES (1,'A'), (2,'A'), (3,'B'), (4,'B')

DECLARE @count int = (SELECT COUNT(*) FROM @tablename)

SELECT seq
      ,(SELECT Nm 
          FROM @tablename T2
         WHERE T2.seq = @count +1 - T1.seq) AS [Nm]
  FROM @tablename T1

【讨论】:

  • 这和我这里用的一样。我正在寻找的是还有其他更有效的选择
  • @JayasuryaSatheesh 抱歉,这是一种不同算法的尝试
【解决方案3】:

另一种查询,不使用 OVER 子句

SELECT
    (SELECT MAX(mytable.Seq) FROM mytable) - mytable.Seq + 1 As Seq,
    Nm
FROM mytable
ORDER BY mytable.Seq DESC

【讨论】:

  • 在我看来,与其计算每行的最大值Seq,不如使用CROSS JOIN 只计算一次。
  • CROSS join 可以产生大量的行,而智能查询优化器可以决定只执行一次子选择。事实上,执行计划表明子选择产生了一个与其他行连接的行。 (sqlfiddle.com/#!6/df363/9/0)
【解决方案4】:

我觉得在这里帮忙回答面试问题不太合适,但是由于这个问题太不切实际了,而且这里有很多复杂的答案,所以我提出了这个更简单的解决方案:

DECLARE @MaxSeq INT;
SELECT @MaxSeq = MAX(Seq) FROM Table;


UPDATE Table 
Set Seq = @MaxSeq - Seq + 1

【讨论】:

    猜你喜欢
    • 2014-05-22
    • 2015-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    相关资源
    最近更新 更多