【问题标题】:Skip rows in query based on data根据数据跳过查询中的行
【发布时间】:2010-10-22 01:23:44
【问题描述】:

我有如下数据

DECLARE @tmp TABLE(cid int, colspan int, rowspan int, corder int)
INSERT INTO @tmp
SELECT 1,2,null,1
UNION
SELECT 2,null,null,2
UNION
SELECT 3,null,null,3
UNION
SELECT 4,3,null,4
UNION
SELECT 5,null,null,5
UNION
SELECT 6,null,null,6
UNION
SELECT 7,null,null,7

我要查询返回

cid   colspan  rowspan  corder
-------------------------------------
1      2       null      1
3      null    null      3
4      3       null      4
7      null    null      7

记录将按 corder 排序,然后使用 colspan 值跳过下一个记录(如果 colspan = 2 跳过下一个 1,如果 3 跳过下一个 2)。使用查询可以做到这一点吗?

为什么我想要这些数据 - 我正在尝试将此数据绑定到转发器控件(表格模板)以创建动态表格,并且当 colspan > 0 时,我不希望我的转发器生成 td 项,以便正确跨越。

【问题讨论】:

  • 在代码中做这种事情比在 sql 中容易得多

标签: .net sql sql-server sql-server-2005 sql-server-2008


【解决方案1】:

因为(正如@Sam Saffron 在 cmets 中所说)在过程代码中执行此类操作确实要容易得多,这意味着您的表不是为 SQL 设计的。

在 SQL 数据库中,每一行都应描述单个实体(或实体之间的单个关系)。如果一个足够常见的设计缺陷没有这样做。例如,考虑这个工资表:

CREATE TABLE Payroll
(
 employee_number CHAR(10) NOT NULL
    REFERENCES Personnel (employee_number), 
 effective_date DATE NOT NULL, 
 salary_amount DECIMAL(19, 4) NOT NULL
    CHECK (salary_amount >= 0), 
 UNIQUE (effective_date, employee_number)
);

INSERT INTO Payroll (employee_number, effective_date, salary_amount)
   VALUES ('U83GHVPSGP', '2001-01-01', 5000), 
          ('U83GHVPSGP', '2002-01-01', 7000), 
          ('U83GHVPSGP', '2002-01-01', 9000);

这里的问题是它是对期间进行建模,但每个期间的结束日期是从另一行的开始日期得出的,即实体(作为单个工资期间)使用两行建模,每个开始日期在数据库。副作用是一个简单的查询,例如“让我知道雇员 U83GHVPSGP 的工资是 5000 MNT”是很重要的(从实现的角度来看,它会涉及一个相关的子查询,它可能在给定的情况下表现不佳SQL 平台)。上表将遭受不明显的异常,例如删除 U83GHVPSGP 收到 7000 MNT 的行将隐式更改另一行上的数据,即现在似乎 U83GHVPSGP 在 '2002-01-01' 之前支付了 5000 MNT,但实际上并非如此。

您有一个名为 rowspan 的列这一事实是我所见过的关于这种设计缺陷的“气味”最完美的例子。

我的意思不是听起来很苛刻。毫无疑问,您的表对于过程代码非常有意义,因此请使用过程代码而不是 SQL。

SQL 最适用于基于集合的解决方案,因此,如果您想使用 SQL,请考虑重新设计您的表,以便在与实体之间的关系不同的表中对实体进行建模,并确保两种类型的表都不会拆分单个实体/关系的数据跨多行。

【讨论】:

  • 你能给我一个桌子设计的小例子吗?我还是不清楚
【解决方案2】:

尝试使用递归 CTE,如下所示:

with cte as (
select t.* from @tmp t where corder = 1
union all 
select t.* from @tmp t join cte c on t.corder = (c.corder + coalesce(c.colspan,1))
)
select * from cte

【讨论】:

  • corder 不正常时不起作用 例如:将 cid 4 的corder 更改为 5 和 cid 的 corder 更改为 4。
  • @rs,您的问题明确指出“记录将按 corder 排序”。如果您想更改问题,请更改问题。
  • 很抱歉,是的,当我订购它们时它可以工作。我在想别的东西。
【解决方案3】:

您可以使用返回实际表的 CLR 表值函数。 CLR 函数是您可以用您的母语 C#、VB 等编写的函数,并且 dll 嵌入在数据库中。

从这里了解更多信息:

http://msdn.microsoft.com/en-us/library/ms131103.aspx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    • 2017-10-30
    • 1970-01-01
    相关资源
    最近更新 更多