mysql conditional join depinde de o coloană (Programare, Mysql, Sql, A Se Alătura)

Fatih Donmez a intrebat.

Încerc să implementez un sistem de notificare generic… Am o structură de date ca aceasta;

notification_base:id,type,object
notificiation_sub:id,user_id,not_base_id,lastNotifyTime
notification_action:id,user_id,not_base_id,action,creationDate

Deci, scenariul de bază este, utilizatorul creează un element de bază de notificare prin postarea unui status sau încărcarea unei fotografii și etc. (în acest caz, statusul, fotografia se referă la câmpul de tip din tabelul notification_base și object_id este post_id sau photo_id în funcție de tip) Apoi, utilizatorul se abonează la acest element notification_base… (utilizatorul 3 se abonează la notification_base 5 și ultima notificare este timpul x).

După aceea, un alt utilizator atinge acest element notification_base. (de exemplu, comentează un status sau dă like la o fotografie)Această acțiune este înregistrată în tabela notification_action (user 5 face acțiunea „like” pe 12/02/2011)…

Ceea ce vreau este să extrag elementele notification_base din abonamentul utilizatorului, dacă ultimul notifiytime este mai mic decât o acțiune de notificare, apoi să le unesc cu notification_action… Pot reuși cu acest sql;

Pentru user id 3;

select * from notification_action
                inner join notification_base on notification_action.not_base_id = notification_base.id
                inner join notification_sub on notification_action.not_base_id = notification_sub.not_base_id
                where notification_sub.user_id = 3 and notification_sub.lastShowDate < notification_action.creationDate ;

rezultatul este aproape ceea ce vreau, de exemplu

utilizatorul x a făcut o „acțiune” asupra obiectului tău care are „tip” și object_id la momentul t

dar vreau, de asemenea, să mă alătur la object_id în funcție de tip… Astfel încât să pot afla ce obiect a fost atins… Dar, după cum vedeți, tipul este dinamic, dacă tipul = post, id-ul obiectului se referă la post_id-ul obiectului din tabelul post, dacă tipul = foto, id-ul obiectului se referă la photo_id-ul obiectului din tabelul foto etc..

Am încercat să fac ceva de genul acesta, dar am primit o eroare de sintaxă;

SELECT *
FROM notification_action
INNER JOIN notification_base
    ON notification_action.not_base_id = notification_base.id
INNER JOIN notification_sub
    ON notification_action.not_base_id = notification_sub.not_base_id CASE notification_base.type
            WHEN 'photo'
                THEN (
                        INNER JOIN photo
                            ON photo.id = notification_base.object_id
                        )
            ELSE (
                    INNER JOIN post
                        ON post.id = notification_base.object_id
                    )
            END
WHERE notification_sub.user_id = 3
    AND notification_sub.lastShowDate < notification_action.creationDate;

Știu că nu este corect, este ca un pseudocod.

Comentarii

  • Consultați stackoverflow.com/questions/1255492/conditional-join-in-mysql – ați putea să uniți mai multe interogări împreună, de exemplu, și strategia left join ar funcționa, dar ar necesita, de asemenea, o mulțime de îmbinări dacă aveți multe tabele. –  > Por dash.
  • ok, acum am primit eroarea „The used SELECT statements have a different number of columns”, deoarece structura tabelelor este diferită una de cealaltă și, de asemenea, am nevoie să obțin date diferite din fiecare tabel. –  > Por Fatih Donmez.
1 răspunsuri
John Woo

nu poți crea îmbinări condiționate între tabele. Cel mai bun mod de a face este să utilizați LEFT JOIN și să folosiți CASE în SELECT declarație. Trebuie să aveți specificate coloanele comune pe care doriți să le afișați,

SELECT *,
        (CASE notification_base.type
            WHEN 'photo'
            THEN photo.columnName1
            ELSE post.ColumnName1
        END) as ColumnName1,
        (CASE notification_base.type
            WHEN 'photo'
            THEN photo.columnName2
            ELSE post.ColumnName2
        END) as ColumnName2
FROM notification_action
    INNER JOIN notification_base
        ON notification_action.not_base_id = notification_base.id
    INNER JOIN notification_sub
        ON notification_action.not_base_id = notification_sub.not_base_id
    INNER JOIN photo
        ON photo.id = notification_base.object_id
    INNER JOIN post
        ON post.id = notification_base.object_id
WHERE notification_sub.user_id = 3
    AND notification_sub.lastShowDate < notification_action.creationDate;