2012-01-06 3 views
1

나는 테이블이있는 경우 :SQL 옵션 저장 및 참조

CREATE TABLE Kids (
    kid_id int(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
    kid_name varchar(45) NOT NULL, 
    kid_favcolors (text) NULL, 
    PRIMARY_KEY(kid_id) 
    ) 

을 나는 테이블이 있습니다

INSERT INTO Kids(kid_name, kid_favcolors) VALUES('Joe','1,2,3,4,5'); 
INSERT INTO Kids(kid_name, kid_favcolors) VALUES('Mary','1,2,3'); 
: 쉼표를 통해 좋아하는 색상을 참조하는 행

CREATE TABLE Colors (
    color_id int(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
    color_name varchar(45) NOT NULL, 
    PRIMARY_KEY(color_id) 
) 

이 ID를 분리

Kid 데이터베이스의 각 항목을 반환하는 명령문을 만드는 방법은 무엇입니까? d는 kid_favcolors 열에 있습니다.

예를 들어

:

COLORS: 
 
color_id color_name 
1   yellow 
2   green 
3   blue 
4   purple 
5   red 
6   brown 
7   black 
KIDS: 
 
kid_id  kid_name kid_favcolors 
1   Joe   1,2,3,4,5 
2   Mary  1,2,3 

내가

 
kid_id  kid_name favorite_colors 
1   Joe   yellow, green, blue, purple, red 
2   Mary  yellow, green, blue 

쿼리를 검색하려는 기존 데이터와 데이터베이스 구조에서 실행되고있다. 실현 가능한 솔루션이 없다면 데이터 구조를 재 배열 할 수는 있지만 솔루션에 상당한 시간을 추가 할 것으로 가정합니다. 어느 쪽이든, 도움이 필요합니다.

SELECT STUFF((SELECT ', ' + color_name FROM colors WHERE color_id IN (1,2,3,4,5) FOR XML PATH('')),1, 2, '') AS colors 

     colors 
1  yellow, green, blue, purple, red 

을하지만 더 복잡한 쿼리를 할 때 내가로부터 ID를 당겨 위의 진술을 통합 할 수있는 방법을 찾을 수 없습니다 : 내가 사용하여 데이터베이스에서 색상을 검색 할 수 있어요

키즈 테이블.

SELECT kids.kid_id, kids.kid_name, favorite_colors FROM kids JOIN colors ON colors.id IN kids.kid_favcolors as favorite_colors 

저에게는 효과가있는 것처럼 보이지만 작동하지는 않습니다. 내가 길을 가거나 정말로 닫을 지 확신하지 못한다.

+2

내가 말할 것을 이 경우 디자인이 올바르지 않으면 kid_id 및 color_id가있는 세 번째 테이블을 갖는 것이 더 좋지 않으므로 col or_id의 위치는 kid_id = x ... – ninesided

+0

더 많은 전통적인 다 대다 테이블과 달리 쉼표로 분리 된 ID를 통해 선호하는 색상을 참조하는 것이 더 좋은 이유는 무엇입니까? – dasblinkenlight

+0

내가 말했듯이 이것은 기존 인프라입니다. 위에서 설명한 데이터는 제가 생각할 수있는 첫 번째 시나리오를 사용한 레크리에이션입니다. 아이디어는 데이터베이스와 스크립트를 읽고 수정하는 모든 스크립트를 재구성하지 않고 수정 프로그램을 구현하려고했습니다. 이 경로를 진행할 솔루션이 없다면 쉼표로 구분 된 ID를 여러 테이블로 변환하고 모든 관리 스크립트를 다시 작성하는 스크립트를 작성합니다. – Josh

답변

0

가 나는 해결책을 일했다; 그것은 꽤 아니지만, 그것은 작동합니다.

SELECT 
    kid_id, 
    kid_name, 
    (SELECT STUFF(
    (SELECT ', '+color_name FROM colors WHERE color_id in 
     (SELECT s from SplitString(kid_favcolors,',')) 
    FOR XML PATH('')) 
    ,1,2,'')) AS favorite_colors 
FROM KIDS 
 
kid_id  kid_name favorite_colors 
1   Joe   yellow, green, blue, purple, red 
2   Mary  yellow, green, blue 
제가 DB를 재 작업하고 내가 사용

분할 문자열 기능의 변화를 수용하기 위해 현재의 관리 사이트를 구현하는 방법에 대한 그들에게 이야기 한

:

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
create function [dbo].[SplitString] 
(
    @str nvarchar(4000), 
    @separator char(1) 
) 
returns table 
AS 
return (
    with tokens(p, a, b) AS (
     select 
      1, 
      1, 
      charindex(@separator, @str) 
     union all 
     select 
      p + 1, 
      b + 1, 
      charindex(@separator, @str, b + 1) 
     from tokens 
     where b > 0 
    ) 
    select 
     p-1 zeroBasedOccurance, 
     substring(
      @str, 
      a, 
      case when b > 0 then b-a ELSE 4000 end) 
     AS s 
    from tokens 
) 
0

원래 솔루션에서 필드에 CSV 문자열을 저장하면 1NF가 위반됩니다. 실제로 - 정의에 따르면 - 테이블은 관계로 적합하지 않습니다. 따라서이 경우 문자열을 데이터의 원자 조각으로 처리하고 응용 프로그램 계층에서 분해합니다.

DB 레이어에서 해결하려면 간단히 디자인을 수정하십시오.

enter image description here

+0

데이터를 표준화하는 데 동의하지만 현재 상황은 여전히 ​​존재하며 시간/비용 문제로 귀결됩니다. 데이터를보다 잘 정리하기 위해 데이터베이스를 재 작성하면 SQL 형식보다 훨씬 더 많은 작업을 수행 할 수있는 현재 형식의 데이터를 참조하는 여러 스크립트를 검토하고 편집해야합니다. – Josh