我的数据如下
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项目,以便它能正确跨越。
答案 0 :(得分:3)
因为(正如@Sam Saffron在评论中所说的那样)在过程代码中执行此类操作确实要容易得多,这意味着您的表没有为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支付5000 MNT,直到'2002-01-01'才真正如此。
你有一个名为rowspan
的列的事实是我见过的关于这种设计缺陷的“气味”的最完美的例子。
我并不是说听起来很刺耳。毫无疑问,您的表对过程代码非常有意义,因此使用过程代码而不是SQL。
SQL最适合基于集合的解决方案,因此如果您想使用SQL,那么请考虑重新设计表,以便在实体之间的关系中对单独表中的实体进行建模,并确保表的两种风格不会拆分单个实体/关系的数据跨越多行。
答案 1 :(得分:1)
尝试使用递归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
答案 2 :(得分:0)
您可以使用返回实际表的CLR表值函数。 CLR函数是您可以用您的母语C#,VB等编写的函数,并且dll嵌入在数据库中。
从这里了解更多信息: