I have this table:
title1 title2 type
---------------------
qwe1 xcv2 3
asd1 tzu 7
fgh1 (empty) 4
and I have this query:
SELECT `title1` AS `title`, `type`
FROM `table`
UNION
SELECT `title2` AS `title`, `type`
FROM `table`
ORDER BY `title` ASC, type
(please see fiddle here).
How can I transform this query so that it doesn't display any rows if title2 is empty? Row 1 shouldn't be displayed.
I tried to implement an IF-statement, but I always get a mysql error.
This should cover the empty string and null:
SELECT `title1` AS `title`, `type`
FROM `table`
UNION
SELECT `title2` AS `title`, `type`
FROM `table` where title2 is not null and title2 <> ''
ORDER BY `title` ASC, type
You should use WHERE statement to define condition for your query
SELECT `title1` AS `title`, `type`
FROM `table`
WHERE `title1` IS NOT NULL AND LENGTH(`title1`) > 0
UNION
SELECT `title2` AS `title`, `type`
FROM `table`
WHERE `title2` IS NOT NULL AND LENGTH(`title2`) > 0
ORDER BY `title` ASC, type
When you use UNION, you remove duplicates. Are you sure you don't want to use UNION ALL? In addition, is there any reason that you need to have a title2? It doesn't seem normalized to me.
SELECT title1 AS title, `type`
FROM `table`
UNION ALL
SELECT title2 AS title, `type`
FROM `table`
WHERE title2 IS NOT NULL AND title2 <> ''
See the demo
I think that, instead to check if title2 is not null and title2 <> '', the shortest way is to use COALESCE to convert any Null value to empty, and then check if the result of COALESCE is <> '', like this:
SELECT title1 AS title, `type`
FROM `table`
UNION
SELECT title2 AS title, `type`
FROM `table`
WHERE COALESCE(title2, '') <> ''
and if you don't need to remove duplicates, i think it's better to use UNION ALL instead of UNION.
Related
I have a table of about 5M rows of data (articles). I have the below query for fulltext searching in the title of the articles in two different languages. The problem with it is that it take about 15 seconds to be executed. MySQL version: 5.6.29-log
Here is the query:
SELECT `id`, `title`, `title_fa` FROM
(SELECT `p`.`id` AS `id`, `p`.`title` AS `title`, `p`.`title_fa` AS `title_fa`, `p`.`unique` AS `unique`, `p`.`date` AS `date` FROM `articles` `p` LEFT JOIN `authors` `a` ON `p`.`unique` = `a`.`unique` WHERE 1 AND MATCH (`p`.`title`) AGAINST ('"heat"' IN BOOLEAN MODE)
UNION
SELECT `p`.`id` AS `id`, `p`.`title` AS `title`, `p`.`title_fa` AS `title_fa`, `p`.`unique` AS `unique`, `p`.`date` AS `date` FROM `articles` `p` LEFT JOIN `authors` `a` ON `p`.`unique` = `a`.`unique` WHERE 1 AND MATCH (`p`.`title_fa`) AGAINST ('"گرما"' IN BOOLEAN MODE)) AS `subQuery`
GROUP BY `unique` ORDER BY `date` DESC LIMIT 0,10;
This is the table structure:
CREATE TABLE `articles` (
`id` int(10) unsigned NOT NULL,
`title` text COLLATE utf8_persian_ci NOT NULL,
`title_fa` text COLLATE utf8_persian_ci NOT NULL,
`description` text COLLATE utf8_persian_ci NOT NULL,
`description_fa` text COLLATE utf8_persian_ci NOT NULL,
`date` date NOT NULL,
`unique` tinytext COLLATE utf8_persian_ci NOT NULL,
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci;
ALTER TABLE `articles`
ADD PRIMARY KEY (`id`),
ADD KEY `unique` (`unique`(128)),
ADD FULLTEXT KEY `TtlDesc` (`title`,`description`);
ADD FULLTEXT KEY `Title` (`title`);
ADD FULLTEXT KEY `faTtlDesc` (`title_fa`,`description_fa`);
ADD FULLTEXT KEY `faTitle` (`title_fa`);
MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT;
First improvement step:
By searching is SO I came across this post:
Combining UNION and LIMIT operations in MySQL query
Using the proposed method I changed my query as follow:
SELECT `id`, `title`, `title_fa` FROM
(SELECT `p`.`id` AS `id`, `p`.`title` AS `title`, `p`.`title_fa` AS `title_fa`, `p`.`date` AS `date`, `p`.`unique` AS `unique` FROM `articles` `p` LEFT JOIN `authors` `a` ON `p`.`unique` = `a`.`unique` WHERE MATCH (`p`.`title`) AGAINST ('"heat"' IN BOOLEAN MODE) LIMIT 0,100
UNION
SELECT `p`.`id` AS `id`, `p`.`title` AS `title`, `p`.`title_fa` AS `title_fa`, `p`.`date` AS `date`, `p`.`unique` AS `unique` FROM `articles` `p` LEFT JOIN `authors` `a` ON `p`.`unique` = `a`.`unique` WHERE MATCH (`p`.`title_fa`) AGAINST ('"گرما"' IN BOOLEAN MODE) LIMIT 0,100) AS `subQuery`
GROUP BY `unique` ORDER BY `date` DESC LIMIT 0,10
The performance was astonishing and the query took like 0.04 seconds to execute. The problem was with sorting that I liked to have more recent articles listed first but this query is not able to do so. Also I'm not sure how the next set of results (i.e. the next 10 results - second page of the results) could be retrieved and shown.
Second improvement step:
Searching more on SO I came across this one:
SQL Query - Using Order By in UNION
And my query looked like below:
SELECT `id`, `title`, `title_fa`, `unique`, `date` FROM
(SELECT `p`.`id` AS `id`, `p`.`title` AS `title`, `p`.`title_fa` AS `title_fa`, `p`.`date` AS `date`, `p`.`unique` AS `unique` FROM `articles` `p` LEFT JOIN `authors` `a` ON `p`.`unique` = `a`.`unique` WHERE MATCH (`p`.`title`) AGAINST ('"heat"' IN BOOLEAN MODE) ORDER BY `p`.`date` DESC LIMIT 0,20) AS `subQueryE`
UNION ALL
SELECT `id`, `title`, `title_fa`, `unique`, `date` FROM
(SELECT `f`.`id` AS `id`, `f`.`title` AS `title`, `f`.`title_fa` AS `title_fa`, `f`.`date` AS `date`, `f`.`unique` AS `unique` FROM `articles` `f` LEFT JOIN `authors` `a` ON `f`.`unique` = `a`.`unique` WHERE MATCH (`f`.`title_fa`) AGAINST ('"گرما"' IN BOOLEAN MODE) ORDER BY `f`.`date` DESC LIMIT 0,20) AS `subQueryF`
GROUP BY `unique` ORDER BY `date` DESC LIMIT 0,10
The performance was better but not satisfying as it took about 7 seconds. It brought up another problem that even having GROUP BY unique duplicate rows was still present in the results.
Third step:
I did another test by executing the following query hoping to get better results:
SELECT `p`.`id` AS `id`, `p`.`title` AS `title`, `p`.`title_fa` AS `title_fa`, `p`.`date` AS `date`, `p`.`unique` AS `unique` FROM `articles` `p` LEFT JOIN `authors` `a` ON `p`.`unique` = `a`.`unique` WHERE MATCH (`p`.`title`) AGAINST ('"heat"' IN BOOLEAN MODE) OR MATCH (`p`.`title_fa`) AGAINST ('"گرما"' IN BOOLEAN MODE) GROUP BY `unique` ORDER BY `date` DESC LIMIT 0,10
But the execution time was awful and reached more than 100 seconds.
Any help is more than welcome and thanks in advance.
I have been using mySQL for a while, but have not really wanted to be this efficient till now. I currently have the following code:
SELECT `page_name` AS manufacturer_name
FROM `manufacturers`
WHERE `id` = '$manufacturers_id'
UNION ALL
SELECT `page_name` AS series_name
FROM `series`
WHERE `id` = '$series_id'
Unfortunately this is not doing what I want, it is selecting the right information for me, but it is putting it all under just one column name: manufacturer_name. How do I modify this to select the page name from manufacturers and series separately? This is the current output I am getting:
manufacturer_name
my_manufacturer_name
my_series_name
This is what I would like to have as output (Note: I just used this as a column separator: |):
manufacturer_name | series_name
my_manufacturer name | my_series_name
If your results contain only single row then use
select
(
SELECT `page_name` AS manufacturer_name
FROM `manufacturers`
WHERE `id` = '$manufacturers_id'
) as manufacturer_name,
(
SELECT `page_name` AS series_name
FROM `series`
WHERE `id` = '$series_id'
) as series_name
Another possibility with UNION is
SELECT `page_name` AS manufacturer_name, null as series_name
FROM `manufacturers`
WHERE `id` = '$manufacturers_id'
UNION ALL
SELECT null, `page_name`
FROM `series`
WHERE `id` = '$series_id'
but this returns 2 rows.
I am having table member(id, name , email, altEmail, phone, altPhone, date).
id is unique 1,2,3,4,5,6,7.....520,521.
id email altemail
1 2#h.v 2#T.h
2 3#gy.c -
3 - 4#t.c
I need output as :
id mail
1 2#h.v
1 2#T.h
2 3#gy.c
3 4#t.c
You can use UNION ALL
SELECT `id`, `email` mail FROM t WHERE `email` <> '-'
UNION ALL
SELECT `id`, `altemail` mail FROM t WHERE `altemail` <> '-'
ORDER BY `id`
Demo
Edit for null values
SELECT `id`, `email` mail FROM t WHERE `email` <> '' AND `email` IS NOT NULL
UNION ALL
SELECT `id`, `altemail` mail FROM t WHERE `altemail` <> '' AND `altemail` IS NOT NULL
ORDER BY `id`
Demo
Try this ...
select id, email as mail from member union select id, altemail from member order by id;
I have the query below that uses union.
"SELECT * FROM (
SELECT 1 AS `table`,
`comment_post_id` AS `feed_id`,
`blog_id` AS `from_blog`,
`comment_author` AS `author`,
`comment_content_stripped` AS `feed_title`,
`comment_content` AS `post_content_s`,
`type` AS `type`,
null AS `object_type`,
`comment_date_gmt` AS `date`
FROM `wp_site_comments`
UNION
SELECT 2 AS `table`,
`post_id` AS `feed_id`,
null AS `from_blog`,
`blog_id` AS `author`,
`post_title` AS `feed_title`,
`post_content_stripped` AS `post_content_s`,
`post_type` AS `type`,
null AS `object_type`,
`post_published_gmt` AS `date`
FROM `wp_site_posts`
UNION
SELECT 3 AS `table`,
`object_id` AS `feed_id`,
`blog_id` AS `from_blog`,
`user_id` AS `author`,
null AS `feed_title`,
null AS `post_content_s`,
`type` AS `type`,
`object_type` AS `object_type`,
`date_added` AS `date`
FROM `wp_global_likes`
UNION
SELECT 4 AS `table`,
`object_id` AS `feed_id`,
null AS `from_blog`,
`user_id` AS `author`,
null AS `feed_title`,
null AS `post_content_s`,
`type` AS `type`,
`object_type` AS `object_type`,
`date_added` AS `date`
FROM `wp_global_followers`
) AS tb
ORDER BY `date` DESC"
Basically I wanted to select only the rows where author is in a comma separated values as follows:
eg. $blog_ids = (23, 55, 19, 10) and $user_ids = (22, 55, 19, 40)
The first table in union, the author is comment_author which is a user id.
The second table in union, the author isblog_id` which is a blog id.
The third and fourth table in union, the author is user_id which is a user_id.
Now, I wanted to somehow distinct the author as blog id and user id so my query will select rows where author is in $blog_ids and $user_ids uniquely.
I used,
WHERE author in (" . $blog_ids . ") and it returns correct. Now I wanted to include $user_id.
Please note that $blog_ids and $user_ids may have a same value.
I hope you get what I mean, this is i guess the best explanation I can make.
I have a following db table review_vote
review_id | user_id | status | date_added
2 3 good 20130116135259
3 3 normal 20130116145259
4 2 normal 20130116155259
5 2 good 20130116165259
6 2 good 20130116175259
7 1 great 20130116185259
8 3 good 20130117135259
9 3 normal 20130117145259
currently I can get the highest vote by using the following query:
SELECT review_id FROM review_vote GROUP BY review_id HAVING COUNT(*) =
(
SELECT MAX(x.counts) FROM
(
SELECT review_id, COUNT(*) counts FROM review_vote GROUP BY review_id
)x
)
order by date_added desc
but if i need to get highest vote perday how can i modified the code above? Which means if today were 2013-01-16 I need to get highest vote for yesterday 2013-01-15
my attempt to use date_added = CURDATE() is failed.
SQLFIDDLE: http://sqlfiddle.com/#!2/9a2b5/6
Update query:
CREATE TABLE IF NOT EXISTS `review_vote` (
`review_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`status` varchar(100) NOT NULL,
`date_added` varchar(100) NOT NULL,
KEY `review_id` (`review_id`,`user_id`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `review_vote` (`review_id`, `user_id`, `status`, `date_added`) VALUES
(223, 2, 'lame', '20130116195259');
INSERT INTO `review_vote` (`review_id`, `user_id`, `status`, `date_added`) VALUES(222, 2, 'lame', '20130115195259');
Just add this in your where condition:
DATE_FORMAT(date_added, '%Y-%m-%d') = CURDATE()
Updating as per your error
SELECT review_id FROM review_vote AS RV WHERE DATE_FORMAT(RV.date_added, '%Y-%m-%d') = CURDATE()
GROUP BY review_id HAVING COUNT() =
(
SELECT MAX(x.counts) FROM
(
SELECT review_id, COUNT() counts FROM review_vote GROUP BY review_id
)x
)
Please have a look at demo :demo
SELECT review_id
FROM review_vote
WHERE date_added LIKE '20130115%'
GROUP BY review_id
ORDER BY COUNT(*) DESC
LIMIT 1
But really you ought to consider changing your date_added column to an appropriate temporal type, like DATETIME or TIMESTAMP.
Add the following to your WHERE clause:
`date_added` BETWEEN
DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 DAY), '%Y%m%d')
AND DATE_FORMAT(CURDATE(), '%Y%m%d')
Make sure you have an index on date_added!
Documentation for the date functions is all here: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Life would be easier for you if your date_added column was a native date type.