2016-10-31 4 views
-1

임 집을 짓고 자 할 때 고객이 원하는 기능을 보여주는 보고서를 작성 중입니다. 데이터를 저장하는 방식으로 2 개의 테이블을 조인하고 싶습니다. 조인을 수행하는 것이 어렵습니다.Varchar에 INT 가입 왼쪽

표 1 tbl_Main_Holding이 필드라는 요건을 가지며, 데이터는 VARCHAR로 저장되고 1,4,7

1 = "Eco-Build" 
4 = "Conservatory" 
7 = "Basement" 

표와 같은 다중 값을 가질 수 2 tbl_Features 상기 필드 ID를 갖는 (INT) 난 그게 내가 여러 기능을 선택한 고객의 결과를 보여 어떻게 내 문제는 내 문제가 아니에요 그러나 를 INT하는 VARCHAR로 변환해야하는 것처럼 및 설명 (대 Varchar)

SELECT * FROM dbo.tbl_Main_Holding AS rm 
LEFT JOIN [dbo].[tbl_Features] AS f 
ON rm.Requirements = f.id 

제 1, 실 거예요 작업 아래에 가입 어떻게 도피가 남았 어? 가입 하시겠습니까? 메신저 SQL Server 2008을 사용하고 두 테이블의 데이터가 그대로 저장됩니다. enter image description here enter image description here

+0

요구 사항 필드에서 데이터는 실제로 쉼표로 구분 된 값을 가질 수 있습니까? –

+0

예 데이터가 varchar로 저장되고 "1,4,7"처럼 보입니다. 쉼표로 구분됩니다 – RustyHamster

+0

테이블에 대한 DDL 및/또는 두 테이블에 대한 샘플 데이터를 제공하십시오. – scsimon

답변

4

1 단계는이 테이블 구조를 설계 한 사람을 찾아서 (당신이더라도) 지팡이로 머리를 두들겨 치기위한 것입니다.

2 단계는 테이블을 다시 디자인하기위한 것으로 여기에 필요한 것은 junction table이며 하나의 varchar 열에 여러 개의 정수를 채우지 않아야합니다. 2 단계 끝에서 좋은 측정을 위해 막대기로 원래 디자이너를 다시 공격해야합니다. 당신까지이 돌아 오게해야하는 경우

SELECT * 
FROM dbo.tbl_Main_Holding AS rm 
     LEFT JOIN dbo.tbl_Main_Holding_Requirements AS r 
      ON r.MainHoldingID = rm.ID 
     LEFT JOIN [dbo].[tbl_Features] AS f 
      ON f.ID = r.FeatureID; 

: 당신의 참여는 이제 간단 그래서 지금

CREATE TABLE tbl_Main_Holding_Requirements 
(
    MainHoldingID INT NOT NULL, --FK TO `tbl_main_Holding` 
    FeatureID INT NOT NULL -- FK TO Require `tbl_Features` 
); 

각 요구 사항은, 오히려 목록에 새 항목보다,이 테이블의 행을 나타냅니다 쉼표로 구분 된 목록은, 당신은 프리젠 테이션 계층에서 그것을 할, 또는 SQL-Server's XML Extensions와 수 :

SELECT *, 
     Features = STUFF(f.Features.value('.', 'NVARCHAR(MAX)'), 1, 1, '') 
FROM dbo.tbl_Main_Holding AS rm 
     OUTER APPLY 
     ( SELECT CONCAT(',', f.Description) 
      FROM dbo.tbl_Main_Holding_Requirements AS r 
        INNER JOIN [dbo].[tbl_Features] AS f 
         ON f.ID = r.FeatureID 
      WHERE r.MainHoldingID = rm.ID 
      FOR XML PATH(''), TYPE 
     ) f (Features); 

두 번째 단계는 가능하지 않은 경우, 당신은이 LIKE를 사용하여 주위를 얻을 수 있습니다 : 특징은 하나의 행에 다시 감소해야하는 경우

SELECT * 
FROM dbo.tbl_Main_Holding AS rm 
     LEFT JOIN [dbo].[tbl_Features] AS f 
      ON ',' + rm.Requirements + ',' LIKE '%,' + CONVERT(VARCHAR(10), f.ID) + ',%'; 

다시 한 번, 당신은 다시 XML 확장을 사용할 수 있습니다

SELECT *, 
     Features = STUFF(f.Features.value('.', 'NVARCHAR(MAX)'), 1, 1, '') 
FROM dbo.tbl_Main_Holding AS rm 
     OUTER APPLY 
     ( SELECT CONCAT(',', f.Description) 
      FROM [dbo].[tbl_Features] AS f 
      WHERE ',' + rm.Requirements + ',' LIKE '%,' + CONVERT(VARCHAR(10), f.ID) + ',%' 
      FOR XML PATH(''), TYPE 
     ) f (Features); 

또 다른 옵션은 목록으로 쉼표로 구분 된 값을 분할하는 것입니다 어떤 종류의 Split function을 사용하지만이 기사의 테스트에서 보여 주듯이 목록에서 개별 값에 액세스 할 필요가 없다면 LIKE을 사용하는 것이 더 효율적입니다.

+1

하하 불행히도 나는 데이터베이스 구조를 알지 못했지만이 보고서를 작성한 후 1 단계를 따르게 될 것입니다. – RustyHamster

+1

(나는 효과적인 교수법으로 사람들을 때리는 것이 실제로는 아니지만) 근본적인 문제를 해결하기보다는 근본적으로 해결하는 것이 좋습니다. 수정하기 전에 dba가 더 길어질수록 더 많은 보고서/뷰/프로 시저 등이 테이블과 데이터를 참조하고 수정 시간이 오래 걸리고 오류가 더 많이 발생할 것입니다. – GarethD

+0

전적으로 동의합니다. 불행히도 우리가 가지고있는 데이터에 대한보고의 필요성은 그들이 시스템을 구축하는 동안 필요로 보지 못했습니다. 이제보고가 필요할 때 데이터를 올바르게 표시하는 악몽이 있습니다. – RustyHamster

1

나는 내 댓글에 쓴 것처럼, Is storing a delimited list in a database column really that bad?
당신은 정말 이런 일을 방지하기 위해 데이터베이스를 정상화 읽어 보시기 바랍니다. 나는 이전과 rm.Requirements 열 후 쉼표를 추가 한

SELECT * FROM dbo.tbl_Main_Holding AS rm 
LEFT JOIN [dbo].[tbl_Features] AS f 
ON ',' + rm.Requirements +',' LIKE '%,' + CAST(f.id as varchar(10)) + ',%' 

참고 :

이제 데이터베이스 스키마를 변경할 수 없습니다 가정 사용할 수 like 간단한 트릭이있다 f.id 열 전후에도.

+0

안녕하세요 Zohar 제안을 주셔서 감사하지만 이것은 첫 번째 경기를 다시 가져온다. 예를 들어 클라이언트와 requirments가 1,4,6 인 경우, 하나의 레코드 만 가져옵니다. = 1 "Eco Build"그것은 그들이 요청한 다른 기능을 보여주지 않습니다. – RustyHamster

+0

각 기능에 대한 레코드가 반환되어야합니다. 요구 사항의 3 개 레코드는 1,4와 6입니다. –

+0

안녕하세요 Zohar Im은 한 레코드 만 가져오고 첫 번째 항목과 일치시킵니다 – RustyHamster