Пропустить строки в запросе на основе данных - PullRequest
1 голос
/ 22 октября 2010

У меня есть следующие данные

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

Записи будут упорядочены по кордеру, а затем с использованием значения colspan пропустить следующие записи (если colspan =2 пропустить следующие 1, если 3 пропустить следующие 2).Можно ли это сделать с помощью запроса?

Почему я хочу эти данные - я пытаюсь привязать эти данные к элементу управления повторителем (шаблон таблицы), чтобы создать динамическую таблицу, и когда есть colspan> 0, я не хочумой повторитель для генерации тд предметов, чтобы он правильно охватывал.

Ответы [ 3 ]

3 голосов
/ 22 октября 2010

Потому что (как сказал @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 голос
/ 22 октября 2010

Попробуйте использовать рекурсивный 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
0 голосов
/ 22 октября 2010

Вы можете использовать функции CLR Table Valued, которые возвращают фактическую таблицу. Функции CLR - это функции, которые вы можете написать на своем родном языке C #, VB и т. Д., И DLL встроены в базу данных.

Узнайте больше об этом здесь:

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

...