SQL Server 2008 中的领导

Posted

技术标签:

【中文标题】SQL Server 2008 中的领导【英文标题】:LEAD in SQL Server 2008 【发布时间】:2018-02-28 16:18:27 【问题描述】:

我已经完成了一个包含 LEAD 的存储过程,不幸的是该脚本必须在 2008 年运行,所以有人知道如何在 2008 年实现这一目标吗?

INSERT INTO #ARTICLES(EAN, ID_ART, QTE, PV_NET_HT)
SELECT EAN, ID_ART, QTE_CDE, PA_NET
FROM (
    SELECT TEXTE_LIG,
            CASE WHEN TEXTE_LIG LIKE '%++%' THEN ID_ART ELSE LEAD(ID_ART) OVER (ORDER BY (SELECT NULL)) END AS ID_ART,
            CASE WHEN TEXTE_LIG LIKE '%++%' THEN CHAR01 ELSE LEAD(CHAR01) OVER (ORDER BY (SELECT NULL)) END AS EAN,
            LEAD(QTE_CDE, CASE WHEN TEXTE_LIG LIKE '%++%' THEN 1 ELSE 2 END) OVER (ORDER BY (SELECT NULL)) AS QTE_CDE,
            LEAD(PX_BASE, CASE WHEN TEXTE_LIG LIKE '%++%' THEN 2 ELSE 3 END, NULL) OVER (ORDER BY (SELECT NULL)) AS PX_BASE,
            LEAD(PX_NET, CASE WHEN TEXTE_LIG LIKE '%++%' THEN 2 ELSE 3 END, NULL) OVER (ORDER BY (SELECT NULL)) AS PA_NET
    FROM AMAZON_ACHATS_LIG 
    WHERE ID_ACHATS_ENT = @IDENTITY
) AS LIGNE
WHERE TEXTE_LIG LIKE 'LIN%';

【问题讨论】:

在 sql server 2012 之前,你需要做一个 self join,。 旁注:LEAD(column) OVER (ORDER BY (SELECT NULL)) 是荒谬的。 ORDER BY (SELECT NULL) 表示前导窗口函数将返回任意行。 (注意,任意不等于随机)。 查询工作正常,没有 order by,因为我不希望它们被订购。我必须在 2008 年做到这一点 这很难读。我什至不打算尝试。继续前进。 @user1340587,如果您不想订购它们,为什么要使用 LEAD?这会得到“NEXT”值,这意味着顺序。 【参考方案1】:

要在 2008 年替换 LEAD,您需要对同一张表进行自连接,连接到下一行。为此,最简单的方法是拥有某种连续的 ID,您可以使用 ID + 1 加入记录。如果不存在合适的连续 ID,则在 CTE 中选择您的数据,并向其中添加 row_number。然后在外部查询中使用该 row_number 进行自联接。

顺便提一下,请注意没有“保持数据库顺序”之类的东西。如果您没有为给定查询指定顺序,则 SQL 将决定输出顺序,它可能与条目的顺序相同,也可能完全不同,或者除了少数记录外,可能几乎是相同的顺序.它可能在不同的场合为同一个查询返回完全不同的顺序,这取决于它决定这次使用的查询计划。如果您希望数据保持与输入时相同的顺序,则需要有一个自动递增的标识列以确保这是可能的,否则有一天您将无法获得预期的结果。

在您的查询中,您的各种潜在客户的偏移量为无(与 1 相同)、1、2 和 3,因此您需要自我加入 3 次才能涵盖所有这些选项。然后,在您的查询中,用正确的自联接表中的数据替换每个 LEAD。你想要这样的东西:

WITH BASEDATA AS (
    --THIS IS YOUR BASIC DATA, WITH A ROW NUMBER ADDED
    -- DO THIS AS A CTE, SO YOU CAN JOIN TO IT MULTIPLE TIMES
    SELECT TEXTE_LIG, ID_ART, CHAR01, QTE_CDE, PX_BASE, PX_NET, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RowNo
    FROM AMAZON_ACHATS_LIG 
    WHERE ID_ACHATS_ENT = @IDENTITY
)
INSERT INTO #ARTICLES(EAN, ID_ART, QTE, PV_NET_HT)
SELECT EAN, ID_ART, QTE_CDE, PA_NET
FROM (
    SELECT TEXTE_LIG,
            CASE WHEN TEXTE_LIG LIKE '%++%' THEN ID_ART ELSE B1.ID_ART END AS ID_ART,
            CASE WHEN TEXTE_LIG LIKE '%++%' THEN CHAR01 ELSE B1.CHAR01 END AS EAN,
            CASE WHEN TEXTE_LIG LIKE '%++%' THEN B1.QTE_CDE ELSE B2.QTE_CDE END AS QTE_CDE,
            CASE WHEN TEXTE_LIG LIKE '%++%' THEN B2.PX_BASE ELSE B3.PX_BASE END AS PX_BASE,
            CASE WHEN TEXTE_LIG LIKE '%++%' THEN B2.PX_NET ELSE B3.PX_NET END AS PA_NET
    FROM BASEDATA B0  --THE BASIC DATA
        LEFT OUTER JOIN BASEDATA B1 ON B1.RowNo = B0.RowNo + 1  --This is your LEAD (1) table
        LEFT OUTER JOIN BASEDATA B2 ON B2.RowNo = B0.RowNo + 2  --This is your LEAD (2) table
        LEFT OUTER JOIN BASEDATA B3 ON B3.RowNo = B0.RowNo + 3  --This is your LEAD (3) table
    --WHERE ID_ACHATS_ENT = @IDENTITY  --DON'T NEED THIS AMY MORE, DONE IN CTE
) AS LIGNE
WHERE TEXTE_LIG LIKE 'LIN%';

【讨论】:

我已经在最里面的查询中注释掉了不再需要的 where 子句。事实上,由于该选择是在 basedata CTE 中完成的,因此您现在可以根据需要将两个底部查询合并为一个。

以上是关于SQL Server 2008 中的领导的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2008 中的 PIVOT SQL 数据

SQL Server 2008 中的功能类似于 mysql 中的 GREATEST?

SQL Server 2008 中的截断/清除表变量

SQL Server 2008 中的 MERGE 语句

如何检查 SQL Server 2008 中的多个参数?

SQL Server 2008 中的错误日志记录