비슷한 기본 구조를 가진 여러 테이블이 있습니다.
biopsy_p0
id | biopsy_id | introduced
biopsy_p1
id | biopsy_p0_id | introduced
biopsy_p2
id | biopsy_p1_id | introduced
내 목표는 다음과 같은 종속성의 트 리뷰를 얻는 것입니다.
biopsy_p0.id-> biopsy_p1.biopsy_p0_id-> biopsy_p2.biopsy_p1_id
나는 SQL로만 시도했지만 내 질문에서 알 수 있듯이 나는 그것에 대해 경험이 많지 않습니다. 지금까지 찾을 수있는 모든 것은 계층 적 트리에 대한 참조입니다. 그러나 이들은 항상 내부 참조가있는 하나의 테이블 만 사용합니다.
--- 업데이트 : 이제 PHP로 작업하게 되었기 때문에 정말 좋은 솔루션이 아니며 SQL로 만들 수 있기를 바랐습니다.
PHP 코드 :
$database = DatabaseFactory::getFactory()->getConnection();
// Get all p0 element asociated with the biopsy
$sql = "SELECT *
FROM biopsy_p0
WHERE biopsy_id = :id";
$query = $database->prepare($sql);
$query->execute(array(':id' => $id));
$p0 = $query->fetchAll();
// Get all p1 elements
$sql="SELECT *
FROM biopsy_p0 as p0
RIGHT JOIN biopsy_p1 as p1
ON p0.id=p1.biopsy_p0_id
WHERE biopsy_id = :id;";
$query = $database->prepare($sql);
$query->execute(array(':id' => $id));
$p1 = $query->fetchAll();
for ($i=0; $i < count($p0); $i++)
{
$p1Array = new ArrayObject();
foreach ($p1 as $key => $value)
{
if ($value->biopsy_p0_id == $p0[$i]->id)
{
$p1Array->append($value);
}
$p0[$i]->p1 = $p1Array;
}
unset($p1Array);
}
if ($p0 != NULL){
return $p0;
}
return FALSE;
결과 : 이것이 정확히 필요한 것이지만 PHP는 지저분하고 확인하고 싶은 각 하위 수준에 따라 복잡성이 증가합니다.
details: Array
(
[0] => stdClass Object
(
[id] => 1
[biopsy_id] => 226
[introduced] => 2014-12-31
[p1] => ArrayObject Object
(
[storage:ArrayObject:private] => Array
(
[0] => stdClass Object
(
[id] => 1
[biopsy_id] => 226
[introduced] => 2015-03-18
[biopsy_p0_id] => 1
)
[1] => stdClass Object
(
[id] => 3
[biopsy_id] => 226
[introduced] => 2015-03-17
[biopsy_p0_id] => 1
)
[2] => stdClass Object
(
[id] => 4
[biopsy_id] => 226
[introduced] => 2015-03-18
[biopsy_p0_id] => 1
)
)
)
)
[1] => stdClass Object
(
[id] => 2
[biopsy_id] => 226
[introduced] => 2014-12-31
[p1] => ArrayObject Object
(
[storage:ArrayObject:private] => Array
(
[0] => stdClass Object
(
[id] => 2
[biopsy_id] => 226
[introduced] => 2015-03-31
[biopsy_p0_id] => 2
)
[1] => stdClass Object
(
[id] => 6
[biopsy_id] => 226
[introduced] => 2015-03-01
[biopsy_p0_id] => 2
)
)
)
)
[2] => stdClass Object
(
[id] => 3
[biopsy_id] => 226
[introduced] => 2014-12-31
[p1] => ArrayObject Object
(
[storage:ArrayObject:private] => Array
(
[0] => stdClass Object
(
[id] => 5
[biopsy_id] => 226
[introduced] => 2015-03-11
[biopsy_p0_id] => 3
)
)
)
)
)
SQL 데이터 :
CREATE TABLE IF NOT EXISTS `biopsy` (
`id` int(11) unsigned NOT NULL,
`creation_date` date NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=228 DEFAULT CHARSET=latin1;
INSERT INTO `biopsy` (`id`, `creation_date`) VALUES
(226, '2015-03-08'),
(227, '2015-03-08');
CREATE TABLE IF NOT EXISTS `biopsy_p0` (
`id` int(11) unsigned NOT NULL,
`biopsy_id` int(11) unsigned NOT NULL,
`introduced` date NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
INSERT INTO `biopsy_p0` (`id`, `biopsy_id`, `introduced`) VALUES
(1, 226, '2014-12-31'),
(2, 226, '2014-12-31'),
(3, 226, '2014-12-31'),
(4, 227, '2015-03-14'),
(5, 255, '2015-03-10'),
(6, 255, '2015-03-12');
CREATE TABLE IF NOT EXISTS `biopsy_p1` (
`id` int(11) unsigned NOT NULL,
`biopsy_p0_id` int(11) unsigned NOT NULL,
`introduced` date NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
INSERT INTO `biopsy_p1` (`id`, `biopsy_p0_id`, `introduced`) VALUES
(1, 1, '2015-03-18'),
(2, 2, '2015-03-31'),
(3, 1, '2015-03-17'),
(4, 1, '2015-03-18'),
(5, 3, '2015-03-11'),
(6, 2, '2015-03-01');
ID를 통해 실제 데이터를 저장하는 다른 테이블을 참조하는 하나의 계층 적 관계 테이블을 갖는 것이 더 좋을 것입니다. 그러면 두 개의 테이블 만 포함되고 새 요소가 추가되면 더 유연해질 수 있습니다.
키를 선언하는 것으로 시작하겠습니다.
CREATE TABLE IF NOT EXISTS `biopsy` (
`id` int(11) unsigned NOT NULL primary key,
`creation_date` date NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=228 DEFAULT CHARSET=latin1;
INSERT INTO `biopsy` (`id`, `creation_date`) VALUES
(226, '2015-03-08'),
(227, '2015-03-08');
CREATE TABLE IF NOT EXISTS `biopsy_p0` (
`id` int(11) unsigned NOT NULL primary key,
`biopsy_id` int(11) unsigned NOT NULL,
`introduced` date NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
alter table biopsy_p0 add constraint fk_biopsy
foreign key (biopsy_id)
references biopsy (id)
on update cascade
on delete cascade;
INSERT INTO `biopsy_p0` (`id`, `biopsy_id`, `introduced`) VALUES
(1, 226, '2014-12-31'),
(2, 226, '2014-12-31'),
(3, 226, '2014-12-31'),
(4, 227, '2015-03-14');
-- violates the f.k. introduced
-- (5, 255, '2015-03-10'),
-- (6, 255, '2015-03-12');
CREATE TABLE IF NOT EXISTS `biopsy_p1` (
`id` int(11) unsigned NOT NULL primary key,
`biopsy_p0_id` int(11) unsigned NOT NULL,
`introduced` date NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
alter table biopsy_p1 add constraint fk_biopsy_p0
foreign key (biopsy_p0_id)
references biopsy_p0 (id)
on update cascade
on delete cascade;
INSERT INTO `biopsy_p1` (`id`, `biopsy_p0_id`, `introduced`)
VALUES
(1, 1, '2015-03-18'),
(2, 2, '2015-03-31'),
(3, 1, '2015-03-17'),
(4, 1, '2015-03-18'),
(5, 3, '2015-03-11'),
(6, 2, '2015-03-01');
나는 그들이 무엇인지에 대한 이름을 지정하는 것이 좋습니다. 즉, id 열 id의 이름을 지정하지 말고 모델의 다른 곳에서 이름을 변경하십시오. 예:
CREATE TABLE IF NOT EXISTS biopsy (
biopsy_id int unsigned NOT NULL primary key,
creation_date date NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=228 DEFAULT CHARSET=latin1;
그러나 나는 그것을 제쳐두겠습니다. 이제 데이터가 일관성이 있음을 알았습니다.
select x.id as biopsy_id, x.creation_date
, y.id as biopsy_p0_id, y.introduced as biopsy_p0_introduction
, z.id as biopsy_p1_id, z.introduced as biopsy_p1_introduction
from biopsy as x
left join biopsy_p0 as y
on y.biopsy_id = x.id
left join biopsy_p1 as z
on z.biopsy_p0_id = y.id
order by x.id, y.id, z.id;
+-----------+---------------+--------------+------------------------+--------------+------------------------+
| biopsy_id | creation_date | biopsy_p0_id | biopsy_p0_introduction | biopsy_p1_id | biopsy_p1_introduction |
+-----------+---------------+--------------+------------------------+--------------+------------------------+
| 226 | 2015-03-08 | 1 | 2014-12-31 | 1 | 2015-03-18 |
| 226 | 2015-03-08 | 1 | 2014-12-31 | 3 | 2015-03-17 |
| 226 | 2015-03-08 | 1 | 2014-12-31 | 4 | 2015-03-18 |
| 226 | 2015-03-08 | 2 | 2014-12-31 | 2 | 2015-03-31 |
| 226 | 2015-03-08 | 2 | 2014-12-31 | 6 | 2015-03-01 |
| 226 | 2015-03-08 | 3 | 2014-12-31 | 5 | 2015-03-11 |
| 227 | 2015-03-08 | 4 | 2015-03-14 | NULL | NULL |
+-----------+---------------+--------------+------------------------+--------------+------------------------+
7 rows in set (0.00 sec)
남아있는 것은 순전히 프레젠테이션이며 PHP에서 더 잘 수행됩니다.
구조 정보를 하나의 테이블에 유지하는 것이 더 나은지 여부에 대한 일반적인 질문에 대해 고정 수준이 적 으면 솔루션이 좋다고 말할 것입니다.
많은 수준의 경우 또는 숫자를 알 수없는 경우 일종의 재귀 구조가 필요합니다 (이러한 종류의 질문을 할 수있는 수단도 필요하다는 점에 유의하십시오. 요즘 대부분의 DBMS에는 재귀 공통 테이블 표현식이 있지만 MySQL에는 없습니다. 변수로 특정 문제를 해결할 수 있지만 곧 지저분해진다.) Troels Arvin에는 다음 링크 모음이 있습니다.
http://troels.arvin.dk/db/rdbms/links/#hierarchical
유용하다고 생각할 수 있습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다