2010-06-22 3 views
4

첫 번째로 여러 테이블을 쿼리하는 것이 처음이므로 새로운 바보 같은 질문 일지 모르겠다. 어딘가에서 시작! 내가 이해하려면이 쉽게해야한다 그림했습니다MySQL 쿼리 - 두 가지 요소를 기반으로 데이터를 결합한 다음 값에 따라 데이터 정렬 방식을 사용자 정의합니다.

:

http://www.mediumsliced.co.uk/temp/mysqlhelp.jpg

내 첫 번째 테이블 wp_user 몇 가지 열이 - 나는 ID의 USER_EMAIL 및 user_nicename있는 3 열에서 값을 원하는 .
내 두 번째 테이블 wp_usermeta에는 사용자에 대한 메타 데이터를 저장하는 3 개의 열이 있습니다. 이 열은 user_id, meta_key 및 meta_value입니다. 이 테이블의 user_id 값은 항상 wp_user (그림 참조)의 일치하는 ID 값에 해당합니다.

meta_key 필드와 함께 meta_value의 데이터를 결합하고 싶습니다.

SELECT wp_users.ID, wp_users.user_login, wp_users.user_nicename, wp_users.user_email, 
     wp_usermeta.user_id, wp_usermeta.meta_key, wp_usermeta.meta_value 
FROM wp_users, wp_usermeta 
WHERE (wp_users.ID = wp_usermeta.user_id); 

이 내가 필요로하는 모든 정보를 표시하지만 내가 가지고있는 문제는 내가 실제로 개별 열로 meta_key의 데이터와 올바른 행에서 해당 메타 키에 대한 meta_value를 표시 할 것입니다 : 지금까지이있다 해당 사용자의 ID를 기반으로 또한 wp_user_level이없는 사용자는 제외해야합니다. (다시 한 번 알려 드리겠습니다.)

분명히 MySql에 관해 배울 점이 많지만 누구나 나를 안내 할 수 있다면 궁극적으로 나는 정말로 감사 할 것입니다, 만약 당신이 쿼리를 설명 할 수 있다면 그것을 배울 수 있습니다.

감사합니다. 더 많은 정보가 필요하거나 무엇인가를 명확히하기 위해 나를 필요로한다면 많이 물어보십시오!

크레이그

+0

EAV 테이블은 극도로 열악한 디자인이며 효과적으로 쿼리하기가 어려우며 실적이 저조합니다. 필요한 열을 정의하고 정규화 된 테이블로 재구성하는 작업을 제안하십시오. – HLGEM

+0

@HLGEM, 나는 그가 그걸로 살아야만한다고 생각한다. -> http://codex.wordpress.org/Database_Description#Table:_wp_usermeta – Unreason

+0

@Unreason - 보너스 기능 : 데이터베이스에 두 가지가 없도록하는 것이 아무것도 없다. meta_key가 같지만 값이 다른 동일한 user_id에 대한 메타 행. – Thomas

답변

2

귀하의 예를

SELECT 
    wp_users.ID, 
    wp_users.user_login, 
    wp_users.user_nicename, 
    wp_users.user_email, 
    wp_usermeta.user_id, 
    wp_usermeta.meta_key, 
    wp_usermeta.meta_value 
FROM 
    wp_users, wp_usermeta 
WHERE 
    (wp_users.ID = wp_usermeta.user_id) AND (wp_usermeta.wp_user_level = 0); 

는 당신이 필요로하는 무엇을 제공해야합니다 계속. 주 :

  • 형식으로 귀하의 SQL 대신 ID = USER_ID에 조건이, 그것은이 같은

가입 수 있었다 WHERE 다음의

  • :

    SELECT 
        ... 
    FROM 
        wp_users INNER JOIN 
        wp_usermeta ON wp_users.id = wp_usermeta.user_id 
    WHERE 
        wp_usermeta.wp_user_level = 0 
    

    편집 :로 메타 데이터 및 메타 속성의 경우 속성이있을 때마다 메타 테이블에 여러 번 가입해야합니다.

    당신이 EAV 접근 방식을 볼 수 있듯이 그것은 UI 요소의 큰 재사용 할 수 있지만

    그래서 예는 데이터베이스의 실제 구조 (느리고 복잡한 쿼리 제한을위한 경이를하지 않습니다,

    SELECT 
        wp_users.ID, 
        wp_users.user_login, 
        wp_users.user_nicename, 
        wp_users.user_email, 
        m1.meta_value as first_name 
        m2.meta_value as last_name 
        m3.meta_value as address 
        m4.meta_value as dob 
    FROM 
        wp_users 
        INNER JOIN wp_usermeta m ON wp_users.id = m.user_id AND m.meta_key = "wp_user_level" AND m.meta_value = 0 
        LEFT JOIN wp_usermeta m1 ON wp_users.id = m1.user_id AND m1.meta_key = "first_name" 
        LEFT JOIN wp_usermeta m2 ON wp_users.id = m2.user_id AND m1.meta_key = "last_name" 
        LEFT JOIN wp_usermeta m3 ON wp_users.id = m3.user_id AND m1.meta_key = "address" 
        LEFT JOIN wp_usermeta m4 ON wp_users.id = m4.user_id AND m1.meta_key = "dob"  
    

    을 취득하는 무결성 검증 및 이러한 구조에서 작동하는 최종 코드에서 더 복잡합니다.

    올바른 방법은 응용 프로그램 수준에서 '집계'를 처리하는 것입니다.

  • +0

    신속한 답변 Unreason을 주셔서 대단히 감사합니다. 그러나 문제는 wp_user_level이 실제로 값이며 이미 기존의 열이 아니라는 것입니다. wp_user_level은 wp_usermeta.meta_key 열 내의 값이므로 먼저 해당 값과 wp_usermeta.meta_vale (해당 열은 값이 아닌)의 해당 값을 대상으로 지정해야합니다. 그래서 당신이 제공 한 코드에 대해 알려지지 않은 컬럼 오류가 발생합니다. 내가 제공 한 그림에 wp_user_level이 어디에 있는지 알면 감각이 좋지 않을 수 있습니다. 잘못된 서식에도 유감입니다! – Craig

    +0

    @Craig, wp_user_level ... editing ...에 대해 알게되었습니다. 두 번째 것은 필요한 것을 제공해야하며 첫 번째 쿼리에서도 수정합니다. – Unreason

    +0

    화려한 답변, 빠른 답장을 보내 주셔서 다시 한번 감사 드리며, 여기에 무슨 일이 벌어지고 있는지 확실히 알고 싶습니다. 너희들은 내가이 분야의 기초를 알면 안된다는 것을 깨닫게 해준다. 이런 종류의 것들을 해결하는 속도는 비현실적입니다! – Craig

    1

    모든 키가 wp_usermeta에 있다고 가정하면 테이블을 여러 번 조인 할 수 있습니다. 값이 누락 된 경우에는 Left Join을 사용하십시오.

    Select 
        u.ID, 
        u.user_login, 
        u.user_nicename, 
        u.user_email, 
        m_first_name.meta_value As first_name, 
        m_last_name.meta_value As last_name, 
        m_address.meta_value As address, 
        m_dob.meta_value  As dob 
    From wp_users u 
    Join wp_usermeta m_first_name On ( m_first_name.user_id = u.id 
                And m_first_name.meta_key = 'first_name') 
    Join wp_usermeta m_last_name On ( m_last_name.user_id = u.id 
                And m_last_name.meta_key = 'last_name') 
    Join wp_usermeta m_address On ( m_address.user_id  = u.id 
                And m_address.meta_key  = 'address') 
    Join wp_usermeta m_dob  On ( m_dob.user_id   = u.id 
                And m_dob.meta_key   = 'dob') 
    Join wp_usermeta m_user_level On ( m_user_level.user_id = u.id 
                And m_user_level .meta_key = 'm_user_level') 
    Where m_user_level.meta_value = '0'; 
    
    +0

    은 값이 존재하는지 미리 알지 못하는 EAV 테이블을 쿼리하는 경우 조인을 남겨 둘 필요가 있습니다. – HLGEM

    +0

    @HLGEM : 맞아요, 나는 쿼리하기 전에 텍스트에서 그것을 다루려고했습니다. –

    +0

    +1, 나는 나의 대답에있는 마지막 버전을 편집했다 - 기본적으로 동일. 또 다른 접근법은'id IN (SELECT user_id FROM wp_usermeta WHERE meta_key = "wp_user_level"AND meta_value = '0')'을 사용하는 것입니다. 또한 쿼리에 마지막으로 조인 된 테이블의 키에 복사/붙여 넣기 아티팩트가 있습니다. m_dob? .meta_key = 'm? _user_level' – Unreason

    0

    당신이 빼고 싶은 각 값에 대해 메타 테이블에 별도로 참여해야합니다. 이것은 EAV 테이블이 관계형 데이터베이스의 안티 패턴 (anti-pattern) 인 이유 중 하나입니다.

    또한 명시 적 조인을 수행하는 방법을 배우십시오. 암시 적 조인은 상황이 복잡 해지면 우발적 인 교차 조인을 초래할 수 있으므로 문제가 발생할 수 있습니다 (이처럼 가난한 디자인만으로 복잡한 쿼리를 작성하게됩니다). 조인을 남겨 둘 필요가있을 때도 좋지 않습니다. 당신이 돈으로 나쁜 디자인이 제안서 할 필요가, 사람이 각 attriubute에 대한 vlue이있는 경우 t 알고

    +0

    데이터를 얻는 방법이 최고가 아니며 실제로는 끔찍합니다. .유일한 것은 모든 데이터를 그대로 유지하는 데 많은 의존성이 있다는 것입니다. 이것은 내가 데이터를 사용하는 것에 추가 된 것이고 무대 1에서 생각하지 못했기 때문에 나는 그것을보고 싶어합니다. 이것은 드물게 사용되는 쿼리로, 서버로드가 플러그인 재 구축 및 데이터 이전과 비교할 때 이것이 나에게 가장 좋은 옵션이라고합니다. 당신의 의견에 진심으로 감사드립니다. – Craig

    3
    Select wp_users.ID 
        , wp_users.user_login 
        , wp_users.user_email 
        , wp_users.user_nicename 
        , Min(Case When wp_usermeta.meta_key = 'first_name' Then wp_usermeta.meta_value End) As first_name 
        , Min(Case When wp_usermeta.meta_key = 'last_name' Then wp_usermeta.meta_value End) As last_name 
        , Min(Case When wp_usermeta.meta_key = 'address' Then wp_usermeta.meta_value End) As address 
        , Min(Case When wp_usermeta.meta_key = 'dob' Then wp_usermeta.meta_value End) As dob 
    From wp_user 
        Join wp_usermeta 
         On wp_usermeta.user_id = wp_user.ID 
    Where Exists (
           Select 1 
           From wp_usermeta As Meta1 
           Where Meta1.user_id = wp_user.id 
            And Meta1.meta_key = 'wp_user_level' 
            And Meta1.meta_value = '0' 
           ) 
         And wp_usermeta.meta_key In('first_name','last_name','address','dob')     
    Group By wp_users.ID 
        , wp_users.user_login 
        , wp_users.user_email 
        , wp_users.user_nicename 
    

    는 첫째, 다른 사람이 언급 한 것처럼, 그 이유 중 하나가이 쿼리가 있다는 것이다 쓰기 너무 복잡입니다. 당신은 EAV 구조를 사용해야 만합니다. "메타"테이블의 개념은 관계형 디자인에 대한 저주입니다. 둘째, EAV에서 정보를 얻으려면 빌드 할 크로스 탭 쿼리를 만들어야합니다. 일반적으로 관계형 데이터베이스는 직접 작성 (on-the-fly) 컬럼 생성을 위해 설계되지 않았습니다. 나는 내 솔루션에서하고 있으며 EAV에 필요합니다.

    +0

    +1 다른 접근 방식의 경우 OP가 성능 비교 – Unreason

    +0

    '+ 1'을 수행하면 좋을 것입니다. 다중 외측 조인 솔루션보다 성능이 좋을 것으로 기대하지만 성능은 테스트해야합니다. –

    +0

    @Peter Lang, @Unreason - 성능이 더 나아질 지 말하기가 어렵습니다. 나는 그것이 얼마나 많은 외부 조인이 필요하고 얼마나 많은 데이터가 테이블에 존재 했느냐에 달려 있다고 생각한다. 외부 조인 접근법을 사용하는 유일한 방법은 user_id + meta_key가 고유 한 것으로 사용되는 것으로 간주되는 TBH입니다. 동일한 user_id에 대해 두 개의 동일한 meta_key 값이있는 경우, 외부 조인은 출력에서 ​​중복 행을 제공합니다. 물론, 그건 내 솔루션이 임의로 두의 "최소"값을 선택했다. – Thomas

    관련 문제