Как преобразовать отношение «многие ко многим» из таблицы с двумя столбцами? - PullRequest
0 голосов
/ 10 марта 2012

Предположим, у меня есть таблица базы данных (пример кода ниже), в которой хранятся отношения между двумя списками (требования и тестовые случаи в моем случае), и я хочу создать таблицу со строками, показывающими тестовые случаи, и столбцами, отображающими требования, с индикатором, показывающим, чтосуществует связь.

Несколько ограничений

  • Я не могу позволить себе роскошь изменять структуру БД, поскольку она относится к открытой системе управления тест-кейсами (TestLink).
  • Можно написать некоторый код для этого, но я надеюсь, что это можно сделать в MySQL.
  • Ах, и да, он использует MySQL, так что это должно работать в этой среде.
  • Эта функциональность раньше существовала, но была исключена, потому что обычно этот тип работы ставит db на колени, когда существуют десятки тысяч тестовых случаев и требований.

    создать таблицу pivot (req_id int (11), testcase_id int (11));

    / * Данные для таблицы pivot * /

    вставитьв pivot (req_id, testcase_id) значения (1,1);

    вставить в pivot (req_id, testcase_id) значения (2,2);

    вставить в pivot (req_id, testcase_id) значения (3,3);

    вставить в pivot (req_id, testcase_id) значения (4,1);

    вставить в pivot (req_id, testcase_id) значения (5,2);

    вставить в pivot (req_id, testcase_id) значения (6,3);

    вставить в pivot (req_id, testcase_id) значения (2,1);

    вставить в pivot (req_id, testcase_id) значения (3,2);

Я хочу получить из запроса таблицу, которая выглядит примерно так:

   1    2    3    4    5    6
1  x    x         x
2       x    x         x
3            x              x

Примечание. Строка - это testcase_ids, а столбцы -'req_ids'

У кого-нибудь есть совет, как получить это только с помощью SQL?

Ответы [ 3 ]

1 голос
/ 10 марта 2012
select testcase_id, 
  if(sum(req_id = 1), 'X', '') as '1', 
  if(sum(req_id = 2), 'X', '') as '2', 
  if(sum(req_id = 3), 'X', '') as '3', 
  if(sum(req_id = 4), 'X', '') as '4', 
  if(sum(req_id = 5), 'X', '') as '5', 
  if(sum(req_id = 6), 'X', '') as '6'
from pivot
group by testcase_id;

Это ужасно, но работает:

+-------------+---+---+---+---+---+---+
| testcase_id | 1 | 2 | 3 | 4 | 5 | 6 |
+-------------+---+---+---+---+---+---+
|           1 | X | X |   | X |   |   | 
|           2 |   | X | X |   | X |   | 
|           3 |   |   | X |   |   | X | 
+-------------+---+---+---+---+---+---+
3 rows in set (0.00 sec)
1 голос
/ 10 марта 2012

ниже намного эффективнее:

создать одну таблицу для test_cases, например

create table testCases(
id int(11) auto_increment,
testcase varchar(200),
primary key(id))

одна таблица для требований

requirements(
id int(11) auto_increment,
requirements varchar(200),
primary key(id))

затем в третьей таблице сопоставим соотношение

 create table matchRequirementsToTests(
 requirements varchar(200),
 testcase varchar(200),
primary key(requirements, testcase),
foreign key (requirements) references Requirements(id),
foreign key(test case) references Test_cases(id))
0 голосов
/ 13 марта 2012

Теперь у меня есть имя для того, чего я пытаюсь достичь. Это «динамическая кросс-таблица». Вот как я дошел до решения. Спасибо http://rpbouman.blogspot.com/2005/10/creating-crosstabs-in-mysql.html за четкие инструкции для получения здесь.

Линии 1-20 - настроить таблицу для использования.

Строки 22-29 - «статический» перекрестный запрос, предполагающий, что я знаю, сколько у меня требований Спасибо D Mac за решение, которое вы дали:)

Линии 30-44 - Запрос, который динамически генерирует статический запрос выше.

Строки 45-72 - Вот тут у меня проблема. Цель состоит в том, чтобы создать хранимую процедуру, которая возвращает результат динамического запроса. MySQL говорит, что есть проблема с синтаксисом, но я не вижу, как это исправить. Есть мысли?

drop table if exists pivot;

create table `pivot` ( 
`req_id` int(11), 
`testcase_id` int(11) 
); 

/*Data for the table `pivot` */ 

insert into `pivot`(`req_id`,`testcase_id`) values (1,4); 
insert into `pivot`(`req_id`,`testcase_id`) values (2,4); 
insert into `pivot`(`req_id`,`testcase_id`) values (3,4); 
insert into `pivot`(`req_id`,`testcase_id`) values (4,7); 
insert into `pivot`(`req_id`,`testcase_id`) values (1,7); 
insert into `pivot`(`req_id`,`testcase_id`) values (2,12); 
insert into `pivot`(`req_id`,`testcase_id`) values (3,12); 
insert into `pivot`(`req_id`,`testcase_id`) values (4,4); 

select * from pivot;

select testcase_id
,        if(sum(req_id = 1), 1, 0)
,        if(sum(req_id = 2), 1, 0)
,        if(sum(req_id = 3), 1, 0)
,        if(sum(req_id = 4), 1, 0)
from pivot
group by testcase_id;

select concat(
      'select testcase_id','\n'
      , group_concat(
         concat(
                ',        if(sum(req_id = ',p2.req_id,'), 1, 0)','\n'
          )
          order by p2.req_id
          separator ''
        )
      , 'from pivot','\n'
      , 'group by testcase_id;','\n'
      ) statement
from pivot p2
order by p2.req_id;

CREATE PROCEDURE p_coverage()
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
begin
    select concat(
                  'select testcase_id','\n'
                  , group_concat(
                     concat(
                            ',        if(sum(req_id = ',p2.req_id,'), 1, 0)','\n'
                      )
                      order by p2.req_id
                      separator ''
                    )
                  , 'from pivot','\n'
                  , 'group by testcase_id;','\n'
                  ) statement
    into @coverage_query
    from pivot p2
    order by p2.req_id;

    prepare coverage from @coverage_query;

    execute coverage;

    deallocate prepare coverage;
end;

select * from pivot;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...