2011-12-01 2 views
2

다른 테이블의 일부 ID (dp_business_locations)를 쉼표로 구분하여 포함하는 'dealBusinessLocations'라는 필드가 있습니다 ('dp_deals'테이블에서).in() 함수로 저장된 mysql 함수에서 반환 된 값을 사용하는 방법은 무엇입니까?

dealBusinessLocations 
---------------------- 
0,20,21,22,23,24,25,26 

이 값은 쿼리의 in() 함수 내에서 사용해야합니다.

select * from dp_deals as d left join dp_business_locations as b on(b.businessLocID IN (d.dealBusinessLocations) ; 

사인 MySQL은 임의의 문자열 기능을 폭발 지원하지 않는 것처럼, 나는 기능이 완벽하게 작동하는 저장 기능

delimiter // 
DROP FUNCTION IF EXISTS BusinessList; 
create function BusinessList(BusinessIds text) returns text deterministic 
BEGIN 
    declare i int default 0; 
    declare TmpBid text; 
    declare result text default ''; 
    set TmpBid = BusinessIds; 
    WHILE LENGTH(TmpBid) > 0 DO 
      SET i = LOCATE(',', TmpBid); 
      IF (i = 0) 
        THEN SET i = LENGTH(TmpBid) + 1; 
      END IF; 
      set result = CONCAT(result,CONCAT('\'',SUBSTRING(TmpBid, 1, i - 1),'\'\,')); 
      SET TmpBid = SUBSTRING(TmpBid, i + 1, LENGTH(TmpBid)); 
    END WHILE; 
    IF(LENGTH(result) > 0) 
     THEN SET result = SUBSTRING(result,1,LENGTH(result)-1); 
    END IF; 
    return result; 
END// 
delimiter ; 

을 만들었습니다.

mysql> BusinessList('21,22') 
BusinessList('21,22') 
----------------------- 
'21','22' 

그러나 함수를 사용하는 쿼리는 작동하지 않습니다. 여기 쿼리입니다.

select * from dp_deals as d left join dp_business_locations as b on(b.businessLocID IN (BusinessList(d.dealBusinessLocations))); 
나는 또한 기능 argumet 정적 값을 사용하여 시도

, 그러나 아무 소용이

select * from dp_deals as d left join dp_business_locations as b on(b.businessLocID IN (BusinessList('21,22'))); 

이 함수에서 반환 된 값을 사용하여 몇 가지 문제가있는 것 같다.

+0

이 테이블을 정규화. 그때까지'FIND_IN_SET()'함수를 사용하십시오. –

답변

3

첫째, 읽기 : Is storing a comma separated list in a database column really that bad?
Yes, it is

그런 가서 테이블을 정상화.

select * from dp_deals as d left join dp_business_locations as b on FIND_IN_SET(b.businessLocID, d.dealBusinessLocations) 

그런 다음, 다시 그 기사를 읽고 당신이 정말로 그렇지 않으면 할 수없는 경우가 정상화 될 때까지


지금, 또는, FIND_IN_SET() 기능을 사용하십시오.쿼리가 느린 경우 또는이 테이블에 다른 문제가있는 경우에, 당신은 이유를 알 수 :

Is storing a comma separated list in a database column really that bad?
Yes, it is

+1

데이터베이스의 +1 CSV는 순수한 악마이며 곧바로 당신을 지옥으로 보낼 것입니다. – Johan

+2

@Johan - 그것이 지옥에 곧바로되지는 않을 것이고, 그것은 당신이 당신의 길을 길로 가도록 만들 것입니다! – MatBailie

+0

CSV 필드가 큰 문제라는 것을 알고 있지만 데이터베이스 스키마를 변경할 수 없습니다. 도와 줘서 고마워. –

0

나는 문제가 있다고 생각한다. IN()은 많은 필드가있는 하나의 문자열을 얻지 만 많은 필드를 필요로한다고 생각한다. 함수와

이를 보내는 :

WHERE something IN ('\'21\',\'22\''); /* i.e. a single text containing "'21','22'" */ 

그리고 간단하지 예상

WHERE something IN ('21','22'); 
+0

Plz 위에 게시 된 기능의 출력을 확인하십시오. 즉. mysql> 비즈니스리스트 ('21, 22 ') 비즈니스리스트 ('21, 22') ----------------------- '21', '22 '. 올바른 형식을 반환합니다. –

+1

@SijoKurian - 문자열이 의도 한 형식입니다. 그러나 @ Cylindric의 답은 여전히 ​​하나의 문자열이라는 것입니다. * 숫자 목록이 아닙니다. 문자열에 숫자와 쉼표 등을 나타내는 문자가 있기 때문에 여러 항목의 목록이되지는 않습니다. 그 안에 모든 문자가 포함 된 * one * 문자열 일뿐입니다. 당신이해야 할 일은 단지 하나의 문자열 대신에 * 많은 * 문자열 테이블을 반환하는 것입니다. 그럼 당신은 할 수있어'어디서나 (선택 *에서 함수())' – MatBailie

+1

@Dems 말합니다, 그렇지 않습니다. * 여러 문자열 또는 숫자를 반환해야하며, 사이에 쉼표가있는 여러 숫자처럼 보이는 하나의 문자열이 아닙니다. – Cylindric

2

사용 find_in_set()을 대신.

SELECT * 
FROM dp_deals as d 
LEFT JOIN dp_business_locations as b 
     ON (FIND_IN_SET(b.businessLocID,d.dealBusinessLocations) > 0); 

참조 : 당신이 CSV 드롭과 지옥 떨어져 나갈 경우 조인 간단하게 사용할 수있는 http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set

주 같은 : 훨씬 빠르고 정규화 A와 것

SELECT d.*, GROUP_CONCAT(b.dealBusinessLocation) as locations 
FROM dp_deals as d 
LEFT JOIN dp_business_location as b 
     ON (d.dealBusinessLocation = b.businessLocID); 

보너스.

+0

두 개의 매개 변수가 역순으로 있다고 생각합니다. –

+0

나는 csv 문제에 대해 귀찮게 생각하지만 데이터베이스 디자인을 변경할 수는 없습니다. find_in_set()이 정상적으로 작동합니다. 귀하의 도움에 감사드립니다 –

+0

ypercube가 맞습니다 –