2012-09-14 2 views
2

내 데이터베이스에서 사용자를 검색하고 각각에 대해 다른 테이블에 JOIN ON을 만들고 싶습니다.MySQL - Like + JOIN

USERS : 여기 내 테이블입니다 id, firstname, lastname, [...] - 사용자의 데이터

FRIENDS

함유 : fan_id, idol_id이, [...]이 - 사용자가 다음을하는 사용자

나는 관계 betwe를 포함하는 얻을 친구 테이블에 원하는, 그래서 지금

SELECT `id`, `username`, `firstname`, `lastname`, `lang`, `twitter`, `facebook`, `picture`, `regdate` 
FROM `users` 
WHERE `username` LIKE ? 
OR `email` LIKE ? 
OR `firstname` LIKE ? 
OR `lastname` LIKE ? 
OR `twitter` LIKE ? 
OR `facebook` LIKE ? 
ORDER BY `username`; 

:

여기 내 검색 쿼리, 고전 검색 한 사용자와이를 요구하는 사용자. 검색된 사용자가 fan_ididol_id 또는 반대로으로 검색 사용자로 나타나는 경우

SELECT `id`, `username`, `firstname`, `lastname`, `lang`, `twitter`, `facebook`, `picture`, `regdate`, 
GROUP_CONCAT(
    CONCAT_WS(':', `fan_id`, `idol_id`) SEPARATOR ';' 
) AS relations 
FROM `friends`, `users` 
WHERE (`username` LIKE ? 
OR `email` LIKE ? 
OR `firstname` LIKE ? 
OR `lastname` LIKE ? 
OR `twitter` LIKE ? 
OR `facebook` LIKE ?) 
AND (
(`fan_id` = 100 AND `idol_id` = `id`) 
OR 
(`fan_id` = `id` AND `idol_id` = 100) 
) 
ORDER BY `username`; 

는 사실, 난 relations에 싶어 : 여기

내가 생각하는 것이다. 하지만 첫 번째 쿼리를 사용하여 사용자를 검색하면 2 명의 사용자가 있습니다 (ids = 80 & 125). 두 번째 쿼리와 함께, 난 단지 1 행 (ID = 80)가 있지만, relations 나는 또한 그 결과 만약을 갖고 싶어, 내가 작업 쿼리의 절반을 말한다 100:80;100:125 ... 내용

을 보여주고있다 (relations에서) 아니기 때문에 IFNULL(..., 0)을 시도했지만 더 이상 설명하지 않았습니다.

도움 주셔서 감사합니다.

+0

실제로 원하는 것을 이해하는 것은 정말 어렵습니다. fan_id는 자신과 다른 사용자 간의 관계를 확인하는 사용자의 ID입니까? 그리고 검색 대상 사용자가 검색을 수행하는 사용자의 팬인지 우상인지를 사용자가보고 싶습니까? 왜 당신은이 결과를 연결하고 있습니까? 두 열, 즉 우상과 부채를 두 개씩 갖고 사실이든 거짓이든 상관없는 이유는 무엇입니까? – mrmryb

+0

네, 죄송합니다. 사실 저는 사용자를 검색하고 사용자를 검색하는 사용자와 관계를 맺고 싶습니다. 그럼 PHP에서는, 그냥 관계를 계산해야합니다 (2는 서로를 따라 가며, 1은 내가 따르고있는 사람을 확인해야한다는 것을 의미합니다) – Max13

+0

나는 당신을 위해 생각해 낸 또 다른 쿼리를 포함하도록 내 대답을 편집했습니다. – mrmryb

답변

2

사용중인 구식 오메가 조인 모델을 사용하는 것보다 표준 JOIN 구문을 사용하는 것이 훨씬 쉽습니다.

다중 테이블 쿼리에서 열 이름을 정규화해야합니다.

소위 리드 테이블로 조인을 시작하십시오. 귀하의 경우 사용자 당 행이 필요하므로이를 사용하여 조인을 시작하십시오.

WHERE에있는 OR 조건의 긴 계단식은 쿼리가 제대로 수행되지 않게합니다. 대신 FULLTEXT (바이너리 모드) 검색을 고려할 수 있습니다.

Backticks는 가독성을 저해하며 표나 열의 이름이 예약어와 같은 경우를 제외하고는 필요하지 않습니다.

쿼리에 GROUP_CONCAT 요약 기능이 있지만 해당 GROUP BY 절이 없습니다. 둘 다 필요합니다. (GROUP BY은 필요하지 않지만 가능한 디버깅 할 때 사용할 수있는 언어 바로 가기가 있습니다.)

조인 기준을 파악하려고하는데 이해가 안됩니다. id = 100에 대해 특별한 것을 이해하지 못합니다. 그러나 참여의 두 번째 부분에서 fan_id = 100이 아닌 idol_id = 100을 찾으시겠습니까?

   (f.fan_id = u.id AND f.idol_id = 100) 

귀하가 갖고있는 것이 프로젝트의 외부인에게는 논리적으로 보이지 않습니다.

난 당신이 시도 제안 :

SELECT u.id, u.username, 
     u.firstname, u.lastname, 
     u.lang, u.twitter, u.facebook, 
     u.picture, u.regdate, 
     GROUP_CONCAT(CONCAT_WS(':', f.fan_id, f.idol_id) SEPARATOR ';') AS relations 
    FROM users u 
    JOIN friends f ON (     
      (f.fan_id = 100 AND f.idol_id = u.id) 
       OR 
      (f.fan_id = u.id AND f.idol_id = 100) 
      ) 
WHERE u.username LIKE ? 
    OR u.email LIKE ? 
    OR u.firstname LIKE ? 
    OR u.lastname LIKE ? 
    OR u.twitter LIKE ? 
    OR u.facebook LIKE ? 
GROUP BY u.id, u.username, 
     u.firstname, u.lastname, 
     u.lang, u.twitter, u.facebook, 
     u.picture, u.regdate 
ORDER BY u.username 
+0

저는 궁금 해서요.하지만 오메가 조인이라고하는 구식 ANSI SQL-86 JOIN 구문을 들어 보지 못했습니다. 그 용어는 어디에서 왔습니까? –

+0

어디서나 읽었는지 모르겠습니다. 그러나 이전에 일해온 오랜 오라클 매장의 일부 동료들이 그렇게 불렀다. 왼쪽 조인을위한'a.id = b.id (+)'문법에서 온 것일 수 있습니다. –

+0

@OllieJones 순서대로 : 1) 나는 이것을 끝낼 때'FULLTEXT'를 찾을 것입니다. 2) 백팁은 내 자신의 가독성을위한 것이며, 틀린 경우이를 제거 할 것입니다. 3) GROUP_CONCAT 및 GROUP BY T_T에 대해 알지 못했습니다. 4) 당신 말이 맞아요, 나는'idol_id'를 의미했습니다. 100은 다른 사용자를 검색하는 user_id입니다. 최종) 귀하의 질의는 내가 찾고있는 것에 가깝습니다. 그러나 기존 사용자 중 하나는 '100'과 두 번째 사용자 사이에 상호 작용이 없으므로 표시되지 않습니다. 기본 값이 필요합니다. 고맙습니다. – Max13

3

이것은 내가 당신을 어떻게 생각하는지의 추측 떨어져 기반을 목표로하고 있습니다 :

select users.id,users.firstname, 
case 
when CONCAT_WS(';',t1.fans,t2.idols)='' then null 
else CONCAT_WS(';',t1.fans,t2.idols) 
end as relations 
from users left join 
(
select CONCAT_WS(':',fan_id,idol_id) as fans,idol_id 
from friends 
where fan_id=80 
) as t1 
on users.id=t1.idol_id 
left join 
(
select CONCAT_WS(':',fan_id,idol_id) as idols,fan_id 
from friends 
where idol_id=80 
) as t2 
on users.id=t2.fan_id 
where id=100 

Sqlfiddle은 ID (100)와 사용자에 대한 결과입니다 누가 ID가 80 인 사용자를 검색하고 있습니까?

where fan_id=80where idol_id=80은 검색 할 사용자의 올바른 ID로 설정하고 where id=100은 검색을 수행하는 사용자를 찾기위한 고리로 대체 될 수 있습니다. 또는 세 가지를 모두 제거하고 모든 사람의 관계 목록을 얻을 수 있습니다.

--- 편집 ---

Sqlfiddle

이 쿼리는 한 번만 한 번만 친구와 사용자를 통해 덜 상세하지만 검색을 제공합니다; 구체적으로 idol 및 fan 열에 더 이상 id를 보유하지 않으며이 열은 1 또는 null입니다. 1은 사용자가 다른 사용자의 것임을 의미하므로 사용자 125는 사용자 100을 검색하고 fan - null | idol - 1을 가지며 이것은 사용자 100의 팬이 아니라 사용자 100의 우상이라는 것을 의미합니다. 댓글은 팬과 아이돌 모두 2, 그 중 하나는 1, 둘 다 아니요는 0입니다.

select users.id,users.firstname,sum(t1.fan) as fan,sum(t1.idol) as idol, 
case 
when t1.fan is null and t1.idol is null then null 
else count(*) 
end as relations 
from users 
left join 
(
select fan_id,idol_id, 
case when fan_id=100 then 1 end as idol, 
case when idol_id=100 then 1 end as fan 
from friends 
where fan_id=100 or idol_id=100 
) as t1 
on users.id=t1.fan_id or users.id=t1.idol_id 
where firstname like '%user1%' 
group by id 

검색 할 사용자의 ID를 변경해야하는 곳은 모두 100 개입니다. 하단의 where 절은 원하는대로 채워질 수 있습니다.

+0

안녕하세요! 나는 당신의 쿼리와 이전 쿼리를 섞어서 만들었습니다. 유일한 문제는 결과가 없을 때 여전히 행이 하나 밖에 없으므로'= ''가 아니라는 것입니다 (2 명의 사용자가 사용자 이름 LIKE % 최대 %를가집니다) . 어쨌든 고마워요. – Max13

+0

@ Max13 미안하지만 문제를 정말로 이해하지 못합니다. 관계형 성냥이 없다면'relations = null'이됩니다. 그리고'2 명의 사용자가 사용자 이름 LIKE % max % '를 가지고 무엇을해야합니까? 사용자가 여러 가지 검색 결과를 얻으면 검색 결과가 잘못 표시된다는 말입니까? 당신이 아직 문제가 있고 나를 원한다면 계속 도와 줄 테니 알려주세요.또한 3 개의 열, 관계 수 (2는 서로를 따르고, 1은 팬 또는 우상, 0은 둘 다 아님)와 함께이를 수행 한 다음 널 또는 id를 가질 수있는 팬 및 우상 열을 선택했습니다. – mrmryb

+0

@ Max13 이와 비슷한 것 - [sqlfiddle] (http://sqlfiddle.com/#!2/9a1cb/7) – mrmryb