需要有关复杂MySQL查询的帮助

时间:2011-08-07 04:53:31

标签: mysql sql

我很难为3表分层数据集获得最终结果集。希望这些图表能说明我拥有的和我正在尝试做的事情。简而言之,我的最终结果集(下面)应该可以轻松地允许我在我的网站中定义动态数量的复选框,同时还允许我定义是否检查这些框,所有这些都来自单个结果集。我相信,由于数据已经标准化,我应该能够得到一个结果集,但我无法理解这个问题......有人可以帮忙吗?

    TABLE A                    TABLE B                 TABLE C       
    MEMBER                     CONTACT                 ALERT     
(pk)$member_id  ->         (pk)$contact_id  ->       (pk)$alert_id     
                           (fk)$member_id            (fk)$contact_id    
                                                         $alert_type ->   
                                                             -> 'local', 'state', 'nation'

我的过滤条件示例是member_id = 1 AND alert_type ='local'

* = results of filter member_id = 1

TABLE MEMBERS A
+----------+----------+
|member_id |   Name   |
+----------+----------+
|     1    |   Alan   | *
|     2    |   Brad   |
|     3    |   Doug   |
|     4    |   Flo    |
+---------------------+

TABLE CONTACTS B 
+--------------------------------------------------------------------+
| contact_id |  member_id  |    email      |    phone     |   Name   |
+------------+-------------+---------------+--------------+----------+
|     1      |     1       |  a@gmail.com  |              |   Alex   | *
|     2      |     1       |  b@gmail.com  | 123-456-7890 |   Bob    | *
|     3      |     3       |  c@gmail.com  |              |   Cris   |
|     4      |     1       |  d@gmail.com  |              |   Dan    | *
|     5      |     2       |  e@gmail.com  |              |   Ed     |
|     6      |     1       |  f@gmail.com  |              |   Fran   | *
|     7      |     1       |  g@gmail.com  | 212-323-1111 |   Greg   | *
|     8      |     2       |  h@gmail.com  |              |   Hans   |
|     9      |     3       |  i@gmail.com  |              |   Ida    |
|    10      |     1       |  j@gmail.com  | 945-555-1212 |   Jeff   | *
|    11      |     2       |  k@gmail.com  | 945-555-1212 |   Karl   |
|    12      |     3       |  l@gmail.com  |              |   Leo    |
+--------------------------------------------------------------------+

# = resutls of filter alert_type = 'local'
TABLE CONTACTS_SELECTED C
+-----------------------------------------+         
|  alert_id  | contact_id |  alert_type   |
+------------+------------+---------------+         
|     1      |     1      |     local     | * #
|     2      |     1      |     state     | *
|     3      |     3      |     state     |
|     4      |     5      |     local     |
|     5      |     5      |     state     |
|     6      |     6      |     nation    | *
|     7      |     7      |     local     | * #
|     8      |     8      |     nation    |  
|     9      |    10      |     local     | *
|    10      |    12      |     state     |
+-------------------------+---------------+

需要的输出

+------------------------------------------------------------------------------------+
|member_id | contract_id  |    email      |    phone     |   Name   |   alert_type   |
+----------+--------------+---------------+--------------+----------+----------------+
|     1    |      1       |  a@gmail.com  |              |   Alex   |    local       |
|     1    |      2       |  b@gmail.com  | 123-456-7890 |   Bob    |     NULL       |
|     1    |      4       |  d@gmail.com  |              |   Dan    |     NULL       |
|     1    |      6       |  f@gmail.com  |              |   Fran   |    nation      |
|     1    |      7       |  g@gmail.com  | 212-323-1111 |   Greg   |    local       |
|     1    |     10       |  j@gmail.com  | 945-555-1212 |   Jeff   |    local       |
+------------------------------------------------------------------------------------+

With this result set, I should be easily able to FOREACH my way through all 6 records and create a checkbox for each record, and flag those records with 'local' as checked. Can anyone help with setting up this complex query?  

--
-- Table structure for table `contacts`
--

CREATE TABLE IF NOT EXISTS `contacts` (
  `contact_id` int(12) NOT NULL AUTO_INCREMENT,
  `member_id` int(12) NOT NULL,
  `email` varchar(30) NOT NULL,
  `phone` varchar(15) NOT NULL,
  `name` varchar(30) NOT NULL,
  PRIMARY KEY (`contact_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=13 ;

--
-- Dumping data for table `contacts`
--

INSERT INTO `contacts` (`contact_id`, `member_id`, `email`, `phone`, `name`) VALUES
(1, 1, 'a@gmail.com', '', 'Alex'),
(2, 1, 'b@gmail.com', '123-456-7890', 'Bob'),
(3, 3, 'c@gmail.com', '', 'Cris'),
(4, 1, 'd@gmail.com', '987-654-3210', 'Dan'),
(5, 2, 'e@gmail.com', '', 'Ed'),
(6, 1, 'f@gmail.com', '', 'Fran'),
(7, 2, 'h@gmail.com', '234-567-8901', 'Hans'),
(8, 3, 'i@gmail.com', '', 'Ida'),
(9, 1, 'g@gmail.com', '', 'Greg'),
(10, 1, 'j@gmail.com', '456-789-0123', 'Jeff'),
(11, 2, 'k@gmail.com', '945-555-1212 ', 'Karl'),
(12, 3, 'l@gmail.com', '', 'Leo');

CREATE TABLE IF NOT EXISTS `contacts_selected` (
  `alert_id` int(12) NOT NULL AUTO_INCREMENT,
  `contact_id` int(12) NOT NULL,
  `alert_type` varchar(6) NOT NULL,
  PRIMARY KEY (`alert_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=12 ;

--
-- Dumping data for table `contacts_selected`
--

INSERT INTO `contacts_selected` (`alert_id`, `contact_id`, `alert_type`) VALUES
(1, 1, 'local'),
(2, 1, 'state'),
(3, 3, 'state'),
(4, 5, 'local'),
(5, 5, 'state'),
(6, 6, 'nation'),
(7, 7, 'local'),
(8, 8, 'nation'),
(9, 10, 'local'),
(10, 12, 'state'),
(11, 1, 'nation');

CREATE TABLE IF NOT EXISTS `alert_types` (
  `alert_type` varchar(6) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

--
-- Dumping data for table `alert_types`
--

INSERT INTO `alert_types` (`alert_type`) VALUES
('local'),
('state'),
('nation');


SOLUTION:
$alert_type = 'local';
// choices are local, state, nation
//
SELECT c.contact_id, c.member_id, c.email, c.phone, c.desc, s.alert_type 
FROM contact c
    LEFT JOIN contact_select s 
    ON c.contact_id = s.contact_id
WHERE c.member_id = 1 AND c.contact_id NOT IN
(SELECT cs.contact_id FROM contact_select cs WHERE cs.alert_type = '$alert_type')
GROUP BY c.contact_id 
UNION
SELECT * FROM 
    (SELECT c.contact_id, c.member_id, c.email, c.phone, c.desc, s.alert_type 
    FROM contact c
    LEFT JOIN contact_select s 
    ON c.contact_id = s.contact_id
    WHERE c.member_id = 1 
    AND s.contact_id 
    IN (SELECT cs.contact_id FROM contact_select cs WHERE cs.alert_type = '$alert_type')) z
WHERE z.alert_type = '$alert_type'

3 个答案:

答案 0 :(得分:1)

我会试试这个:

select `c`.`contact_id`, `member_id`, `email`, `phone`, `name`, `alert_type` from contacts `c`
left join contacts_selected `s` on `c`.`contact_id` = `s`.`contact_id`
where member_id=1
group by `c`.`contact_id`

然而,有两点:第一,我不清楚你想如何缩小结果集以只选择其中一种警报类型。第二,您的样本数据和插入语句包含的数据略有不同。这不是问题,但最初有点令人困惑。

答案 1 :(得分:0)

select member_id, cs.contract_id, c.email, c.phone, c.name, cs.alert_type 
FROM contact c
LEFT JOIN contact_selected cs on cs.contact_id = c.contact_id
WHERE c.member_id = 1

我不确定我的理解是什么意思,但也许你在寻找这个?

答案 2 :(得分:0)

这可以为您提供所需的输出。

SELECT C.member_id, C.contact_id, C.email, C.phone, C.name, S.alert_type 
FROM CONTACTS C 
    LEFT OUTER JOIN CONTACTS_SELECTED S
        ON C.contact_id = S.contact_id 
WHERE member_id = 1