Join tables with comma values

北慕城南 提交于 2019-11-28 14:40:00

I recommend that you make your joins explicit.
It makes it easier to debug your query and to change inner with left joins.
There is absolutely never a good reason to use SQL '89 implicit join syntax.

SELECT ni.*
       , nf.*
       , group_concat(nm.mailgroup_name) as mailgroups
FROM newsletter_items ni
INNER JOIN newsletter_fields nf 
  ON (nf.field_letter_uid = ni.letter_id)
INNER JOIN newsletter_mailgroups nm  
  ON (find_in_set(nm.mailgroup_id, ni.receivers))
WHERE  
  nf.field_name = 'letter_headline' 
  ni.template = '". $template ."' 
GROUP BY ni.letter_id;

Regarding your database design.
I recommend you normalize your database, that means that you move the comma separated fields into a different table.

So you make a table receivers

Receivers
----------
id integer auto_increment primary key
letter_id integer not null foreign key references newsletter_items(letter_id)
value integer not null

You then remove the field receiver from the table newsletter_items

Your query then changes into:

SELECT ni.*
       , group_concat(r.value) as receivers
       , nf.*
       , group_concat(nm.mailgroup_name) as mailgroups

FROM newsletter_items ni
INNER JOIN newsletter_fields nf 
  ON (nf.field_letter_uid = ni.letter_id)
INNER JOIN newsletter_mailgroups nm  
  ON (find_in_set(nm.mailgroup_id, ni.receivers))
LEFT JOIN receiver r ON (r.letter_id = ni.letter_id)
WHERE  
  nf.field_name = 'letter_headline' 
  ni.template = '". $template ."' 
GROUP BY ni.letter_id;

This change should also speed up your query significantly.

phil

If it's allowed, why don't you create a new table called newsletter_item_receivers where you could store letter_id, receiver_id fields? Having comma separated values in a field like this usually means you're missing a table :)

Edit:

By using CSV, you are making your life miserable when you want to retrieve an answer to "give me all newsletters that receiver_id=5 receives" :)

Here's a good answer to a similar question on SO: Comma separated values in a database field

Edit2:

If I understand your table relationships correctly then it would be something like this:

SELECT
  a.letter_date,
  b.receiver_id,
  a.status
FROM newsletter_items_receivers b
  LEFT OUTER JOIN newsletter_items a ON (a.letter_id = b.letter_id)
  LEFT OUTER JOIN newsletter_mailgroups m ON (m.mailgroup_id = b.receiver_id)

NOTE! This query WILL NOT return a newsletter when there are no receivers of that newsletter. If you need that functionality you can try something like this:

SELECT
  x.letter_date,
  y.mailgroup_name,
  x.status
FROM (
SELECT
  a.letter_date,
  b.receiver_id,
  a.status
FROM newsletter_items a
  LEFT OUTER JOIN newsletter_items_rec b ON (b.letter_id = a.letter_id)) x
  LEFT OUTER JOIN newsletter_mailgroups y ON (y.mailgroup_id = x.receiver_id)

I don't have access to SQL right now so I might have made some syntax errors (hopefully not logical ones :)).

As for why we are doing it like this, as @Konerak pointed out, you'd be well advised to read up on database normalization and why it's important.

You can start with this article from about.com, just glanced over it seems an OK read http://databases.about.com/od/specificproducts/a/normalization.htm

Also, it would be good if you'd keep fields names the same across multiple tables. For example you have letter_id in newsletter_items, but you have field_letter_uid in newsletter_fields. Just a thought :)

Try to use

SELECT A.*, B.*, group_concat(C.mailgroup_name SEPARATOR ',') 
FROM newsletter_items A,  newsletter_fields B, newsletter_mailgroups C  
WHERE B.field_letter_uid = A.letter_id 
      AND field_name = 'letter_headline' 
      AND A.template = '". $template ."' 
      and find_in_set(c.mailgroup_id, A.receivers) 
group by A.letter_id;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!