【问题标题】:Customize SQL recordset order by specific value (s) if mentioned如果提到,按特定值自定义 SQL 记录集顺序
【发布时间】:2013-01-04 15:06:48
【问题描述】:

我有一个使用经典 ASP 和 SQL 编写的在线商店 web 应用程序,我需要有关商品订单结果的帮助。

我有一个名为“items”的表,如下所示:

ITEM_NUMBER | DESCRIPTION | PRICE | NEXT_ITEM |
-----------------------------------------------
0001          Item 0001       1.5
-----------------------------------------------
0002          Item 0002       2
-----------------------------------------------
0003          Item 0003       1
-----------------------------------------------
0004          Item 0004       3
-----------------------------------------------
0005          Item 0005       7        0030
-----------------------------------------------
.
.
.
.
-----------------------------------------------
0030          Item 0030       3

我想要做的是保持 ITEM_NUMBER 的顺序,因为 NEXT_ITEM 值为 null,但在项目 0005 之后显示项目 0030,因为它是非常相似的项目,并且项目编号在行中提到项目 0005。 之后需要返回记录集指针以继续从它跳过的地方加载结果(项目 0006)。

一旦记录集到达 0030,我希望它跳过这条记录,因为它已经对用户可见并且之前已经加载过。

【问题讨论】:

  • NEXT_ITEM 链能走多深?你能指定你希望输出的样子吗?跳过已经显示的可能是一个简单的where ITEM_NUMBER not in (select NEXT_ITEM from Items)

标签: sql sql-server select sql-order-by


【解决方案1】:

这似乎可以完成工作 - 您需要将表连接回自身,并优先使用自连接而不是通常的排序键:

declare @T table (ItemNo char(4) not null,Description varchar(20) not null,RelatedItemNo char(4) null)
insert into @T (ItemNo,Description,RelatedItemNo) values
('0001','0001',null),
('0002','0002',null),
('0003','0003',null),
('0004','0004',null),
('0005','0005','0009'),
('0006','0006',null),
('0007','0007',null),
('0008','0008',null),
('0009','0009',null),
('0010','0010',null)

select
    t.*
from
    @T t
        left join
    @T t_par
        on
            t.ItemNo = t_par.RelatedItemNo
order by
    COALESCE(t_par.ItemNo,t.ItemNo),
    t_par.RelatedItemNo

结果:

ItemNo Description          RelatedItemNo
------ -------------------- -------------
0001   0001                 NULL
0002   0002                 NULL
0003   0003                 NULL
0004   0004                 NULL
0005   0005                 0009
0009   0009                 NULL
0006   0006                 NULL
0007   0007                 NULL
0008   0008                 NULL
0010   0010                 NULL

这不能很好地处理一个项目在多个其他行中显示为 RelatedItemNo 的情况 - 它会出现在每个这样的位置。但是,同样,您在问题中没有提到这种可能性,也没有提到处理它的具体规则,所以我不会为此添加任何修复。

此外,如果我们需要将其扩展到多个级别,上述方法仍然不够 - 可以通过引入 CTE 来解决。但是,同样,您在问题中没有提到这种情况。

【讨论】:

  • @Ofirk - 正如我在答案底部提到的那样,存在一些限制 - Paul Williams 提出了类似的问题。如果我们有真实的样本数据和预期的结果,我们可以做更多的事情。如果需要,您可以在 sqlfiddle 网站上设置数据。
  • @ Damien_The_Unbeliever 非常感谢您的回答,这就是我想要的!抱歉,实际上 RelatedItemNo 列在另一个名为 PARAMETERS 的表中,而不是在同一个表 ITEMS 中。在我的 SQL 语句中,我之前已经为此表执行了 FULL JOIN,因为我有一些参数在那里用作语句中的条件。例如,我有: SELECT DISTINCT ItemNo, Description.. FROM ITEMS FULL JOIN PARAMETERS ON ITEMS.ItemNo = PARAMETERS.ItemNo... 当 SELECT 已经包含此表时,如何左连接参数并实现您的代码?谢谢
  • @Orfik - 编辑您的问题以包含详细信息(您可以在此处应用格式)。并且,再次尝试包括样本数据和预期结果。提及您知道的任何边缘情况。
  • @Damien_The_Unbeliever-感谢您的帮助,这是我的演示:sqlfiddle.com/#!3/5abd9/1 您可以看到并非所有行都返回,因为该项目缺货或在“ShowItem”下标记为“NO” '。我需要帮助才能在此 SQL 语句中实现您的代码并以“RelatedItemNo”顺序返回记录,因此预期的输出将是:0001,0002,0007,0004,0005,0009,0006,0008,0009。 (我想在 0003 之后显示 0007,即使项目 0003 因为条件而没有被选中),这是边缘情况,RelatedItemNo 链只会按项目运行,它不会循环。非常感谢。
  • @Damien_The_Unbeliever-在我再次为 PARAMETERS 像这里的示例 sqlfiddle.com/#!3/5abd9/3 一样执行 LEFT JOIN 之后,我收到错误 Ambiguous column name 'SHOWITEM'.: 因为存在冲突LEFT JOIN 后的列名相同。我该如何解决这个问题?谢谢。
【解决方案2】:

根据您的 SQL Server 版本,您可以在表中添加 hierarchyid 列并对其进行排序。

或者,您可以编写递归 CTE 来对结果进行排序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-10
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    相关资源
    最近更新 更多