MYSQL - table display options (do not print duplicates) - mysql

I am looking into the options when printing mysql table. It is simple task but I could not find any help so far.
I have a table (tbl_2) and it looks like that:
+------+------+------+------+--------+---------+
| code | PN | Alt | Link | PN_Val | Alt_Val |
+------+------+------+------+--------+---------+
| 1 | A | B | 1 | 4 | 4 |
| 2 | A | B | 1 | 4 | 1 |
| 3 | B | Z | 0 | 3 | 2 |
| 4 | B | Z | 0 | 3 | 1 |
| 5 | B | Z | 0 | 3 | 3 |
| 6 | F | G | 1 | 2 | 2 |
| 7 | F | G | 1 | 2 | 1 |
+------+------+------+------+--------+---------+
What I am trying to show is the following
+------+------+------+------+--------+---------+
| code | PN | Alt | Link | PN_Val | Alt_Val |
+------+------+------+------+--------+---------+
| 1 | A | B | 1 | 4 | 4 |
| 2 | | | | | 1 |
| 3 | B | Z | 0 | 3 | 2 |
| 4 | | | | | 1 |
| 5 | | | | | 3 |
| 6 | F | G | 1 | 2 | 2 |
| 7 | | | | | 1 |
+------+------+------+------+--------+---------+
In the nutshell I try to have anything that is duplicated removed.
Code for mysql:
create table tbl_2 (
code int(10) primary key,
PN varchar(10),
Alt varchar(10),
Link varchar(10),
PN_Val int(10),
Alt_Val int(10));
insert into tbl_2 values
(1, 'A', 'B', '1', 4, 4),
(2, 'A', 'B', '1', 4, 1),
(3, 'B', 'Z', '0', 3, 2),
(4, 'B', 'Z', '0', 3, 1),
(5, 'B', 'Z', '0', 3, 3),
(6, 'F', 'G', '1', 2, 2),
(7, 'F', 'G', '1', 2, 1);

If you want do that in SQL.
You can try to use a subquery in CASE WHEN
Schema (MySQL v5.7)
create table tbl_2 (
code int(10) primary key,
PN varchar(10),
Alt varchar(10),
Link varchar(10),
PN_Val int(10),
Alt_Val int(10));
insert into tbl_2 values (1, 'A', 'B', '1', 4, 4);
insert into tbl_2 values (2, 'A', 'B', '1', 4, 1);
insert into tbl_2 values (3, 'B', 'Z', '0', 3, 2);
insert into tbl_2 values (4, 'B', 'Z', '0', 3, 1);
insert into tbl_2 values (5, 'B', 'Z', '0', 3, 3);
insert into tbl_2 values (6, 'F', 'G', '1', 2, 2);
insert into tbl_2 values (7, 'F', 'G', '1', 2, 1);
Query #1
SELECT code,
(CASE WHEN code = (select min(code) from tbl_2 tt WHERE tt.PN = t1.PN and tt.Alt = t1.Alt GROUP BY PN,Alt) THEN PN END) PN,
(CASE WHEN code = (select min(code) from tbl_2 tt WHERE tt.PN = t1.PN and tt.Alt = t1.Alt GROUP BY PN,Alt) THEN Alt END) Alt,
(CASE WHEN code = (select min(code) from tbl_2 tt WHERE tt.PN = t1.PN and tt.Alt = t1.Alt GROUP BY PN,Alt) THEN Link END) Link,
(CASE WHEN code = (select min(code) from tbl_2 tt WHERE tt.PN = t1.PN and tt.Alt = t1.Alt GROUP BY PN,Alt) THEN PN_Val END) PN_Val,
Alt_Val
FROM tbl_2 t1;
| code | Alt_Val | PN | Alt | Link | PN_Val |
| ---- | ------- | --- | --- | ---- | ------ |
| 1 | 4 | A | B | 1 | 4 |
| 2 | 1 | | | | |
| 3 | 2 | B | Z | 0 | 3 |
| 4 | 1 | | | | |
| 5 | 3 | | | | |
| 6 | 2 | F | G | 1 | 2 |
| 7 | 1 | | | | |
View on DB Fiddle

As the above comments suggest, this is a requirement which might be best or typically handled in your presentation layer, e.g. something like PHP. But, with MySQL 8+ this is fairly easy to handle with a single query:
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY PN ORDER BY code) rn
FROM yourTable
)
SELECT
code,
CASE WHEN rn = 1 THEN PN ELSE '' END AS PN,
CASE WHEN rn = 1 THEN Alt ELSE '' END AS Alt,
CASE WHEN rn = 1 THEN Link ELSE '' END AS Link,
-- show NULL for missing values in the next two integer columns
CASE WHEN rn = 1 THEN PN_Val END AS PN_Val,
CASE WHEN rn = 1 THEN Alt_Val END AS Alt_Val
FROM cte
ORDER BY code;
Demo

Related

How to exclude more rows by one match

Well, sorry but I don't know how to formulate the subject correctly.
That's why I'd better describe the issue.
I have a kind of following table:
CREATE TABLE IF NOT EXISTS `Test` (
`Id` INT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(5) NOT NULL,
`v1` INT NOT NULL,
PRIMARY KEY (`Id`)
);
INSERT INTO `Test` (`Name`, `v1`)
VALUES ('A', 4), ('A', 3), ('B', 6), ('C', 1), ('C', 2),
('C', 7), ('D', 7), ('D', 5), ('E', 3), ('F', 1),
('F', 2), ('G', 7), ('H', 9), ('H', 1), ('I', 5);
What I need is to find all names that matches e.g. 7.
These are 'C', 'D' and 'G'.
And now I need to select all rows except 'C', 'D' and 'G'.
Resulting table is supposed to be:
===============
| Name | v1 |
|–––––––––––––|
| A | 4 |
| A | 3 |
| B | 6 |
| E | 3 |
| F | 1 |
| F | 2 |
| H | 9 |
| H | 1 |
| I | 5 |
|–––––––––––––|
I've tried the query:
select t1.Name, t1.v1
from `Test` as t1
join (
select Name from `Test`
where v1 = 7
) as t2
on t1.Name != t2.Name
but only realized that I still do not understand the mechanics of JOIN statements.
Hope for some help with this issue.
Thanks in advance.
This query:
SELECT Name FROM Test WHERE v1 = 7
returns all the Names that you want to exclude.
Use it with the operator NOT IN:
SELECT *
FROM Test
WHERE Name NOT IN (SELECT Name FROM Test WHERE v1 = 7)
See the demo.
Results:
> Id | Name | v1
> -: | :--- | -:
> 1 | A | 4
> 2 | A | 3
> 3 | B | 6
> 9 | E | 3
> 10 | F | 1
> 11 | F | 2
> 13 | H | 9
> 14 | H | 1
> 15 | I | 5
You can use not exists:
select t.*
from test t
where not exists (select 1
from test t2
where t2.name = t.name and t2.v1 = 7
);
This selects all rows in test where the name on the row has no row with 7, anywhere in the table.
Here's how to do it with JOINs...
SELECT x.*
FROM test x
LEFT
JOIN test y
ON y.name = x.name
AND y.v1 = 7
WHERE y.id IS NULL;
+----+------+----+
| Id | Name | v1 |
+----+------+----+
| 1 | A | 4 |
| 2 | A | 3 |
| 3 | B | 6 |
| 9 | E | 3 |
| 10 | F | 1 |
| 11 | F | 2 |
| 13 | H | 9 |
| 14 | H | 1 |
| 15 | I | 5 |
+----+------+----+

Show all the groupped value that have same value more than 1

I have table like this
table1
| ID | Val | Val2 |
| 2 | AA | 0 |
| 3 | AA | 1 |
| 4 | AD | 0 |
| 5 | CV | 1 |
| 6 | AF | 1 |
| 7 | CV | 1 |
I want to know if there is duplicate value in column Val more than one. I used the group by clause. plus i want to know how many duplicate appear in Val
select Val,count(Val) from table
group by Val where
having count(val) > 1
result :
| Val | count(val) |
| AA | 2 |
| CV | 2 |
Now i want to know which column that have duplicate value so i used Group_concat with query like this
select Val,count(Val), group_concat(ID) from table1
group by Val where
having count(val) > 1
Results
| Val | count(val) | group_concat(ID) |
| AA | 2 | 2,3 |
| CV | 2 | 5,7 |
Now i dont know how to show all the duplicate value, i only show which id that had duplicate value by group_concat() but i couldn't show all data without the group_concat column. I tried to use Field_in_set but it seems not working.
select Val,count(Val), group_concat(ID) from table1
where FIELD_IN_SET(ID,group_concat(ID))
group by Val where
having count(val) > 1
What i expect is i want to show all the duplicate value after i group by and count the value like below table
| ID | Val | Val2 |
| 2 | AA | 0 |
| 3 | AA | 1 |
| 5 | CV | 1 |
| 7 | CV | 1 |
CREATE TABLE table1 (
`ID` INTEGER,
`Val` VARCHAR(2),
`Val2` INTEGER
);
INSERT INTO table1
(`ID`, `Val`, `Val2`)
VALUES
('2', 'AA', '0'),
('3', 'AA', '1'),
('4', 'AD', '0'),
('5', 'CV', '1'),
('6', 'AF', '1'),
('7', 'CV', '1');
SELECT t1.*
FROM table1 t1
INNER JOIN (SELECT COUNT(`Val`) countval, `Val` FROM table1 GROUP BY `Val`) t2
ON t1.`Val` = t2.`Val`
WHERE countval > 1
ID | Val | Val2
-: | :-- | ---:
2 | AA | 0
3 | AA | 1
5 | CV | 1
7 | CV | 1
SELECT `ID`, `Val`, `Val2`
FROM ( SELECT
`ID`, `Val`, `Val2`,
COUNT(`Val`) OVER(PARTITION BY `Val`) c1
FROM table1) t1
WHERE c1 > 1
ID | Val | Val2
-: | :-- | ---:
2 | AA | 0
3 | AA | 1
5 | CV | 1
7 | CV | 1
db<>fiddle here
If you want to return the rows with the duplicate Vals then use EXISTS:
select t.* from tablename t
where exists (select 1 from tablename where Val = t.Val and ID <> t.ID)
See the demo.
Results:
| ID | Val | Val2 |
| --- | --- | ---- |
| 2 | AA | 0 |
| 3 | AA | 1 |
| 5 | CV | 1 |
| 7 | CV | 1 |

Correlated Subqueries with MAX() and GROUP BY

I have the issue using MAX() and GROUP BY.
I have next tables:
personal_prizes
___________ ___________ _________ __________
| id | userId | specId| group |
|___________|___________|_________|__________|
| 1 | 1 | 1 | 1 |
|___________|___________|_________|__________|
| 2 | 1 | 2 | 1 |
|___________|___________|_________|__________|
| 3 | 2 | 3 | 1 |
|___________|___________|_________|__________|
| 4 | 2 | 4 | 2 |
|___________|___________|_________|__________|
| 5 | 1 | 5 | 2 |
|___________|___________|_________|__________|
| 6 | 1 | 6 | 2 |
|___________|___________|_________|__________|
| 7 | 2 | 7 | 3 |
|___________|___________|_________|__________|
prizes
___________ ___________ _________
| id | title | group |
|___________|___________|_________|
| 1 | First | 1 |
|___________|___________|_________|
| 2 | Second | 1 |
|___________|___________|_________|
| 3 | Newby | 1 |
|___________|___________|_________|
| 4 | General| 2 |
|___________|___________|_________|
| 5 | Leter | 2 |
|___________|___________|_________|
| 6 | Ter | 2 |
|___________|___________|_________|
| 7 | Mentor | 3 |
|___________|___________|_________|
So, I need to select highest title for user.
E.g. user with id = 1 must have prizes 'Second', 'Ter'.
I don't know how to implement it in one query(((
So, first of all, I try to select highest specID for user.
I try next:
SELECT pp.specID
FROM personal_prizes pp
WHERE pp.specID IN (SELECT MAX(pp1.id)
FROM personal_prizes pp1
WHERE pp1.userId = 1
GROUP BY pp1.group)
And it doesnt work.
So please help me to solve this problem.
And if you help to select prizes for user it will be great!
The problem I perceive here is that prizes.id isn't really a reliable way to determine which is the "highest" prize. Ignoring this however I suggest using ROW_NUMBER() OVER() to locate the "highest" prize per user as follows:
Refer to this SQL Fiddle
CREATE TABLE personal_prizes
([id] int, [userId] int, [specId] int, [group] int)
;
INSERT INTO personal_prizes
([id], [userId], [specId], [group])
VALUES
(1, 1, 1, 1),
(2, 1, 2, 1),
(3, 2, 3, 1),
(4, 2, 4, 2),
(5, 1, 5, 2),
(6, 1, 6, 2),
(7, 2, 7, 3)
;
CREATE TABLE prizes
([id] int, [title] varchar(7), [group] int)
;
INSERT INTO prizes
([id], [title], [group])
VALUES
(1, 'First', 1),
(2, 'Second', 1),
(3, 'Newby', 1),
(4, 'General', 2),
(5, 'Leter', 2),
(6, 'Ter', 2),
(7, 'Mentor', 3)
;
Query 1:
select
*
from (
select
pp.*, p.title
, row_number() over(partition by pp.userId order by p.id ASC) as prize_order
from personal_prizes pp
inner join prizes p on pp.specid = p.id
) d
where prize_order = 1
Results:
| id | userId | specId | group | title | prize_order |
|----|--------|--------|-------|-------|-------------|
| 1 | 1 | 1 | 1 | First | 1 |
| 3 | 2 | 3 | 1 | Newby | 1 |
The result can be "reversed" by changing the ORDER BY within the over clause:
select
*
from (
select
pp.*, p.title
, row_number() over(partition by pp.userId order by p.id DESC) as prize_order
from personal_prizes pp
inner join prizes p on pp.specid = p.id
) d
where prize_order = 1
| id | userId | specId | group | title | prize_order |
|----|--------|--------|-------|--------|-------------|
| 6 | 1 | 6 | 2 | Ter | 1 |
| 7 | 2 | 7 | 3 | Mentor | 1 |
You could expand on this logic to locate "highest prize per group" too
select
*
from (
select
pp.*, p.title
, row_number() over(partition by pp.userId, p.[group] order by p.id ASC) as prize_order
from personal_prizes pp
inner join prizes p on pp.specid = p.id
) d
where prize_order = 1
| id | userId | specId | group | title | prize_order |
|----|--------|--------|-------|---------|-------------|
| 1 | 1 | 1 | 1 | First | 1 |
| 5 | 1 | 5 | 2 | Leter | 1 |
| 3 | 2 | 3 | 1 | Newby | 1 |
| 4 | 2 | 4 | 2 | General | 1 |
| 7 | 2 | 7 | 3 | Mentor | 1 |

mysql - show 2 seperate provider name from 1 provider table

And I want my output like the following:
My requirement is the following:
latest service ID
default = 'Y'
How should I write the query? Can someone help me?
You could use this:
select se.svcid, p1.pname as serviceprovider, p2.pname as tmidprovider
from tmid t
inner join (select sno, max(svcid) as maxsvcid from service group by sno) s
on t.sno = s.sno and t.`default` = 'Y'
inner join service se on se.svcid = s.maxsvcid
left join provider p1 on se.pid = p1.pid
left join provider p2 on t.pid = p2.pid;
Table
create table service (svcid int, sno varchar(20), pid int);
insert into service values
(1, '11-11-11-11', 1), (2, '11-11-11-11', 2), (3, '11-11-11-12', 1), (4, '11-11-11-12', 2), (5, '11-11-11-13', NULL);
create table tmid (id int, sno varchar(20), pid int, `default` char(1));
insert into tmid values
(1, '11-11-11-11', 1, 'N'),(2, '11-11-11-11', 2, 'Y'),(3, '11-11-11-12', 1, 'N'),
(4, '11-11-11-12', 2, 'Y'),(5, '11-11-11-13', 2, 'Y'),(6, '11-11-11-13', 3, 'N');
create table provider (pid int, pname varchar(20));
insert into provider values (1, 'Ambank'), (2, 'Citybank'), (3, 'CIMB Bank');
Data
mysql> select * from service;
+-------+-------------+------+
| svcid | sno | pid |
+-------+-------------+------+
| 1 | 11-11-11-11 | 1 |
| 2 | 11-11-11-11 | 2 |
| 3 | 11-11-11-12 | 1 |
| 4 | 11-11-11-12 | 2 |
| 5 | 11-11-11-13 | NULL |
+-------+-------------+------+
mysql> select * from tmid;
+------+-------------+------+---------+
| id | sno | pid | default |
+------+-------------+------+---------+
| 1 | 11-11-11-11 | 1 | N |
| 2 | 11-11-11-11 | 2 | Y |
| 3 | 11-11-11-12 | 1 | N |
| 4 | 11-11-11-12 | 2 | Y |
| 5 | 11-11-11-13 | 2 | Y |
| 6 | 11-11-11-13 | 3 | N |
+------+-------------+------+---------+
mysql> select * from provider;
+------+-----------+
| pid | pname |
+------+-----------+
| 1 | Ambank |
| 2 | Citybank |
| 3 | CIMB Bank |
+------+-----------+
Result
+-------+-----------------+--------------+
| svcid | serviceprovider | tmidprovider |
+-------+-----------------+--------------+
| 2 | Citybank | Citybank |
| 4 | Citybank | Citybank |
| 5 | NULL | Citybank |
+-------+-----------------+--------------+

Need help with a complex MySQL query

I'm struggling to get a final result set for a 3 table hierarchical set of data. Hopefully, the diagrams will indicate what I have and what I'm trying to do. Briefly, my final result set (below) should easily allow me to define a dynamic number of checkboxes in my web site, while also allowing me to define whether the boxes are checked, all from within a single result set. I believe that since the data is normalized, I should be able to get a single result set, but I can't get my head wrapped around this on... Can anyone help??
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'
Example of my filter criteria is 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 |
+-------------------------+---------------+
REQUIRED OUTPUT
+------------------------------------------------------------------------------------+
|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'
This should give you your desired output.
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
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
Not sure i understand well what do you mean but maybe you're looking for thiS?
I would try this:
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`
However, two points: One, it's not clear to me how you want to narrow the result set to select only one of the alert types. Two, your sample data and your insert statments contain slightly different data. That's not a problem, but it is a little confusing at first.