2011-01-12 5 views
3

mysql 데이터베이스 (칵테일 제조법 웹 사이트)에서 중복 결과를 찾는데 문제가 발생했습니다. 여기서 셋업 :MySQL 쿼리 문제 (결과 중복)

표 1의 '칵테일'
[CID, c_name (CID = 고유 칵테일 ID, c_name = 칵테일 이름)

표 2 '재료'
[IID, i_name (IID = 고유 성분 ID, i_name = 성분명)

표 3 'cocktail_ingredients'(링킹 테이블)
[ciid, CID, IID (ciid = 고유 행 식별자 CID = 칵테일 CID, IID = 성분 iid)

그래서 하나의 칵테일은 'cocktail_ingredients'테이블 (1 to many)에 여러 행을 가질 수 있습니다.

설치가 정상입니다. 문제는 현재 데이터베이스에 중복 된 칵테일이 있는지 찾아내는 것입니다. 예를 들어

cocktail_ingredients 테이블이 이러한 항목이 있다면 :

CID를 | iid
1 | 56
1 | 78
1 | 101
. . .
9 | 56
9 | 78
9 | 101

칵테일은 동일합니다 (어쨌든 이론적 인 목적을 위해). 'cocktail_ingredients'테이블이 하나 개 더 행이 있다면

...

9 | 103

다음은 칵테일 번호 9에 추가 재료가 포함되어 있으므로 동일하지 않습니다.

그래서 mysql은 2 가지 검사를 수행해야합니다. 첫째, 성분 수는 동일하고 두 번째로 모든 성분 id (iid)는 해당 칵테일 (cid)과 동일합니다.

이 하나에 난처한 그림이있어 도움을 많이 주셨습니다. 나는 PHP 루트를 따라 가면서 좀 더 복잡한 코드를 작성해야 할 수도 있다고 생각하지만, 거기서 고심하고있어, 이것이 멈추고 물어볼 좋은 장소라고 생각했다.

감사

+0

두 개의 칵테일에 동일한 성분이 들어 있기 때문에 동일한 칵테일 일 필요는 없습니다. 수량은 다양 할 수 있습니다. –

+1

그래, 이걸 이해해 - 왜 내가 "이론적 인 목적으로"말했다. 분명히 혼합하는 방법, 금액 및 다른 변수의 호스트가 그것을 바꿀 수 있습니다. 그러나 그것은 확실히 저를 통해 처음부터 볼 수있는 좋은 기반을 제공합니다. –

답변

1
당신은 세트 평등의 정의가 모두 ABD B가 서로의 하위 집합이 있다는 것을 먼 수학 클래스에서 불러올 수 있습니다

이 (비 엄격한) 그래서 단지를 만들 톤

닉 A에있는 모든 얇은 것이 B에 있는지를 확인하는 뷰 또는 프로 시저를 실행 한 다음 두 개의 칵테일이 서로 서브 세트인지 확인하십시오. 이것은 완전한 대답과는 거리가 멀지 만, 당신을 가게하는 데 충분할 수 있습니다.)

부정으로 처리하는 것이 더 쉬울 것입니다. B에없는 A에서 성분을 찾으십시오.존재하지 않는다면, A는 B의 엄격한 부분 집합이어야한다. (A와 B는 둘 다 비어서는 안된다.)

또는 각 성분 이온 B와 각 성분 A와 B의 계수를 계산한다. 그들이 동일한 경우, 그들은 동등한 칵테일

CREATE VIEW ingredient_count AS 
SELECT cid, count(*) as ingredients 
FROM cocktail_ingredients 
GROUP BY cid 

CREATE VIEW shared_ingredients AS 
SELECT c1.cid cid1, c2.cid cid2, count(*) as ingredients 
FROM cocktail_ingredients as c1 INNER JOIN cocktail_ingredients as c2 
ON (c1.cid != c2.cid AND c1.iid = c2.iid) 
GROUP BY c1.cid,c2.cid 

CREATE VIEW duplicates AS 
SELECT cid1,cid2 
FROM (ingredient_count AS ic1 INNER JOIN shared_ingredients 
     ON ic1.cid=cid1) INNER JOIN ingredient_count as ic2 
    ON ic2.cid=cid2 
WHERE ic1.ingredients=ic2.ingredients 
AND shared_ingredients=ic1.ingredients 

참고이 어디 조항이 아니라 전망보다 합리적인와 부속 선택과 mysql을 훨씬 빠를 수 있습니다,하지만 당신은 확인 TRIGGER를 사용하여 부과 할 수이

+0

감사합니다. 톤이 좋아 보이는데, 수학 수업 시간 기억이 천천히 나에게 돌아옵니다. 나중에 가야겠다. 손가락을 건넜다. –

+0

내 데이터베이스 크기 (칵테일 테이블 3000 레코드 보유, cocktail_ingredients는 12000 이상 보유하고 있으며 성분은 650 개 정도입니다.)에서 느려지는 방식으로 작동한다고 생각합니다. PHP 솔루션을 사용하고있는 임 씨,하지만 다시 까다로운 .... –

+0

@ 닉, 하단에 내 노트를 참조하십시오 - 당신은 속도가 아닌 가독성을 위해 작성한 뷰 (적절한 where 절 포함) 대신 하위 쿼리를 사용하여 속도를 크게 높일 수 있습니다. 내 경험에 의하면 이러한 종류의 쿼리는 30 초 이상에서 몇 초의 짧은 시간 동안 진행될 수 있습니다. – tobyodavies

-1

을 이해하기 쉽게 . 그러나 아직 개념적 문제가 있습니다.

두 개의 칵테일이 {1 | 56, 78, 101}{9 | 56, 78, 101, 103}이고 체크를 구현했다고 가정 해 보겠습니다. 이제

, 당신은 하나의 데이터를 삽입 :

cid | iid 
---------- 
1 | 56 

그런 다음, 나머지 두 재료를 추가 ...

cid | iid 
---------- 
1 | 56 
1 | 78 
1 | 101 

파인, 지금은 9 추가하기 시작 :

cid | iid 
---------- 
1 | 56 
1 | 78 
1 | 101 
9 | 56 

세 가지 이상의 성분을, 그래서 그들을 계속 추가 :

cid | iid 
---------- 
1 | 56 
1 | 78 
1 | 101 
9 | 56 
9 | 78 

두 군데가 더 남아 (101103) 그러나 슬프 도다! 101을 추가 할 수 없습니다! 101을 추가하려고하면 9가 1과 같아 져 트리거가 추가되지 않습니다. 칵테일은 다른 사람의 부분 집합 인 경우

, 당신은 나중에 일부를 추가해야합니다. 나는 당신이 이것을 이해하게 할 수 있었으면 좋겠다.

데이터베이스에 제한을 두지 마십시오. 내가 내 웹 응용 프로그램에서하는 것은 :

칵테일 항목/업데이트 인터페이스에서
  1. , 나는 사용자 입력을 것이다 (그리고 아직 DB에서/업데이 트를 삽입)

  2. 은 사용자가 저장을 클릭하면 버튼 (저장 버튼 추가), 새/업데이트 된 칵테일이 다른 복사본으로 복사되는지 확인하십시오 (저장 프로 시저를 작성하는 경우도 있지만 선택 쿼리 만 사용 가능).

  3. /업데이트 된 칵테일은 다른 데이터베이스의 복제/삽입 데이터베이스와 중복되지 않습니다. If

+0

-1 for 당신은 데이터베이스에 어떤 제한도 두어서는 안됩니다. 이것은 제가 들었던 최악의 조언입니다. – tobyodavies

+0

기존 항목을 정리하기 위해 추가하기위한 제한 사항이 아닙니다. 나는 그것이 "있을지도 모른다"는 약간의 알림을 넣을 수 있지만 기본적으로 멈추지는 않을 것입니다. –

+0

@tobyodevis : plz는 엔티 응답을 읽습니다. 당신은 내가 db 제한이 구현 될 수 있다고 말했다. 그러나 결국, 나는 다른 것을 제안했다. 어쨌든, 트리거를 사용하는 것은 오라클 dba의 매우 일반적인 관행입니다. 그 가장 나쁜 것은 u가 들었을지라도 –