mySQL Group_Concat and Case when query gives error - mysql

I am getting the error "Incorrect parameters in the call to native function 'CONCAT': on the query below:
SELECT
*,
GROUP_CONCAT(
CASE
WHEN `REASONORINSTRUCTIONCODE` = 'R'
THEN CONCAT(
"name-",
`USERWHOENTEREDTHISLINE`,
",reason-",
RTRIM(
`REASONSORSHIPPINGINSTRUCTIONS`
)
END,
", "
)
) AS reason,
GROUP_CONCAT(
CASE
WHEN [ `REASONORINSTRUCTIONCODE` ] = 'S'
THEN CONCAT(
"name-",
`USERWHOENTEREDTHISLINE`,
",shipping instruction-",
RTRIM(
`REASONSORSHIPPINGINSTRUCTIONS`
)
END,
", "
)
) AS shipping instruction
FROM
TABLE
GROUP BY `PICKUP_NO`

You have several issues with your query. First, you're not closing your CONCAT with an end ), next your AS shipping instruction cannot contain a space. Next, you have [REASONORINSTRUCTIONCODE], remove the []
Take a look at the formatted query below:
SELECT
*,
GROUP_CONCAT(
CASE
WHEN `REASONORINSTRUCTIONCODE` = 'R'
THEN CONCAT(
"name-",
`USERWHOENTEREDTHISLINE`,
",reason-",
RTRIM(
`REASONSORSHIPPINGINSTRUCTIONS`
))
END,
", "
)
AS reason,
GROUP_CONCAT(
CASE
WHEN `REASONORINSTRUCTIONCODE` = 'S'
THEN CONCAT(
"name-",
`USERWHOENTEREDTHISLINE`,
",shipping instruction-",
RTRIM(
`REASONSORSHIPPINGINSTRUCTIONS`
))
END,
", "
)
AS shipping_instruction
FROM
`TABLE`
GROUP BY `PICKUP_NO`

Related

return the Nth word from database

I want to get nth word from a column I'm using a code line and it works for me but there is an issue, for example:
First line is: "the Nth word from database"
Second line is: "return the Nth word from database and more words"
When I search for 6th word 'database' it returns my first line and second line but I don't want to get my first line because it has only 5 words.
thank you all
My code line:
SELECT *,
SUBSTRING_INDEX(SUBSTRING_INDEX(`Text`, ' ', 6), ' ', -1) as Nth
FROM `tbl_name`
Having six words in you sentence means that you have to have at least five spaces, adding simlpe condition will resolve your problem:
select *,
case when length(`text`) - length(replace(`text`, ' ', '')) >= 5 then
substring_index(replace(`text`, substring_index(`text`, ' ', 5) , ''), ' ', 2)
else null end Nth
from `tbl_name`
Also I changed your query, because it didn't take into account that you might not have 6th space (exactly six words).
Demo
Or even more concicse:
select *,
substring_index(substring_index(`text`, ' ', 5 - (length(`text`) - length(replace(sentence`text` ' ', ''))) - 1), ' ', 1)
from `tbl_name`
Another demo.
You should update your query with where clause, in where you can count the number of words by the following query.
SELECT *, SUBSTRING_INDEX(SUBSTRING_INDEX(`Text`, ' ', 6), ' ', -1) as Nth
FROM `tbl_name`
where (COUNT(column1) - LENGTH(replace(column1, ' ', '')) > 5
You should have to take count of spaces or whichever string which you want to take & then need to apply having-clause on that count.
SELECT
* ,
SUBSTRING_INDEX( SUBSTRING_INDEX( `text` , ' ', 6 ) , ' ', -1 ) AS Nth,
ROUND( ( LENGTH( `text` ) - LENGTH( REPLACE( `text` , " ", "" ) ) ) / LENGTH( " " ) ) AS countq
FROM `xp_test`
HAVING
countq >= 5

Extracting second word from each row in a column

I have a vendors table in my database that am experimenting with, as shown below
And when i run the sql command below
SELECT vendor_name
FROM vendors
ORDER BY vendor_name
LIMIT 10
I get the output below
My issue is am trying to extract the second word from each vendor_name and when the second word doesn't exist it's supposed to return a blank cell.
And below is the sql query i have written to do just that
SELECT vendor_name,
SUBSTRING(
SUBSTRING( vendor_name, LOCATE(' ', vendor_name) + 1),
1,
LOCATE( ' ', SUBSTRING( vendor_name, LOCATE(' ', vendor_name) + 1) ) - 1
) AS second_word
FROM vendors
ORDER BY vendor_name
LIMIT 10
And here is the output of that sql query
If you notice from the output above, when the words in the vendor_name are more than two, it returns the second word just fine and when the vendor_name contains one word it returns a blank cell as expected.
Problem comes when the vendor_name contains exactly two words, instead of returning the second word it is returning a blank cell for example in the case of American Express and ASC Signs.
How can i better improve my query so that even when the vendor_name does contain two words, it does return the second word instead of a blank cell?
Thank you.
That's because there is no space after the second word, if the text ends there, the locate() has no space to find.
Quick hack: Add a space at the end.
LOCATE( ' ', CONCAT(SUBSTRING( vendor_name, LOCATE(' ', vendor_name) + 1), ' ') ) - 1
SELECT vendor_name , substr(vendor_name , instr(vendor_name, " ") ,
case when LOCATE (' ', vendor_name,instr(vendor_name, " ") ) > 0 then LOCATE (' ',
vendor_name,instr(vendor_name, " ") ) else CHAR_LENGTH (vendor_name) end )
from vendors ;
I took tips from both #stick bit and #kiran gadhe and i came up with this sql query and it's working just fine
SELECT vendor_name,
CASE
WHEN INSTR( vendor_name, ' ' ) = 0
THEN
''
ELSE
SUBSTRING(
SUBSTRING( vendor_name, LOCATE(' ', vendor_name) + 1),
1,
LOCATE( ' ', CONCAT(SUBSTRING( vendor_name, LOCATE(' ', vendor_name) + 1), ' ') ) - 1
)
END AS second_word
FROM vendors
ORDER BY vendor_name
LIMIT 10

How to optimize this MySQL query from Doctrine QueryBuilder?

This query is generated by a doctrine2 QueryBuilder (the concat function takes only 2 parameters), and it takes 4 seconds.
SELECT COUNT(*) AS dctrn_count
FROM
(
SELECT DISTINCT id_4
FROM
(
SELECT 1 / LOCATE( ?, CONCAT( CONCAT( CONCAT(w0_.firstname, ' '),
CONCAT(w0_.lastname, ' ') ), w1_.fullname )
) AS sclr_0,
1 / LOCATE( ?, CONCAT( CONCAT( CONCAT(w0_.firstname, ' '),
CONCAT(w0_.lastname, ' ') ), w1_.shortname )
) AS sclr_1,
1 / LOCATE( ?, CONCAT( CONCAT( CONCAT(w0_.nickname, ' '),
CONCAT(w0_.lastname, ' ') ), w1_.fullname )
) AS sclr_2,
1 / LOCATE( ?, CONCAT( CONCAT( CONCAT(w0_.nickname, ' '),
CONCAT(w0_.lastname, ' ') ), w1_.shortname )
) AS sclr_3,
w0_.id AS id_4, w0_.slug AS slug_5, w0_.firstname AS firstname_6,
w0_.lastname AS lastname_7, w0_.nickname AS nickname_8,
w0_.gender AS gender_9, w0_.email AS email_10, w0_.email_checked AS email_checked_11,
w0_.title_en AS title_en_12, w0_.short_title AS short_title_13,
-- lots of stuff removed (see edit) --
w5_.biography_en AS biography_en_55, w5_.created AS created_56, w5_.updated AS updated_57, w6_.id AS id_58, w6_.web_text AS web_text_59, w6_.created AS created_60
FROM wmn_executive w0_
INNER JOIN wmn_company w1_ ON w0_.company_id = w1_.id
INNER JOIN wmn_industry w7_ ON w1_.industry_id = w7_.id
INNER JOIN wmn_location w2_ ON w1_.location_id = w2_.id
INNER JOIN wmn_country w3_ ON w2_.country_id = w3_.id
INNER JOIN wmn_city w4_ ON w2_.city_id = w4_.id
LEFT JOIN wmn_executive_link w5_ ON w0_.link_id = w5_.id
LEFT JOIN wmn_web_executive w6_ ON w0_.id = w6_.executive_id
WHERE w0_.original_id IS NULL
AND w0_.user_id IS NOT NULL
AND ( w0_.firstname LIKE ?
OR w0_.lastname LIKE ?
OR w0_.nickname LIKE ?
OR w1_.fullname LIKE ?
OR w1_.shortname LIKE ?
OR w0_.title_en LIKE ?
OR w0_.short_title LIKE ?
OR w7_.industry_name_en LIKE ?
OR w7_.industry_name_fr LIKE ?
OR w3_.country_name_en LIKE ?
OR w3_.country_name_fr LIKE ?
OR w4_.city_name LIKE ?
)
ORDER BY sclr_0 DESC, sclr_1 DESC, sclr_2 DESC, sclr_3 DESC ) dctrn_result
) dctrn_table
** The ORDER BY provides no benefit to the end result; remove it.
**
SELECT COUNT(*) AS dctrn_count
FROM
(
SELECT DISTINCT id_4
can be simplified to
SELECT COUNT(DISTINCT(id_4))
** All the items in the SELECT clause are not use, except for id_4; get rid of them.
**** Those 3 optimization might shrink the run time from 4.0s to maybe 3.9s.
And then you will say that this is not the real query, but merely a count?
If you are going to do a messy text scan like that, you need all those strings in one table. Better yet, all the strings concatenated together into one column in one table. This would be just for searching, not for display. Then make a FULLTEXT index on that column. This will solve the OR and LIKE '%...' problems. But how to get it back into doctrine2, I don't know.

Why is this query returning part of itself in the result?

I've not come across this before. Here's the query:
$query="SELECT
CONCAT_WS(' ',
TRIM(SUBSTRING_INDEX(
SUBSTRING(document, 1, INSTR(document, 'Quickstart') - 1 ),
' ',
-8)
),'Quickstart',
TRIM(SUBSTRING_INDEX(
SUBSTRING(document, INSTR(document, 'Quickstart') + LENGTH('Quickstart') ),
' ',
5)
)
)
FROM documents WHERE MATCH(document)
AGAINST('Quickstart' IN BOOLEAN MODE )";
And here's the resulting array:
[0] => Array
(
[CONCAT_WS(' ',
TRIM(SUBSTRING_INDEX(
SUBSTRING(document, 1, INSTR(document, 'Quickstart') - 1 ),
' ',
-8)
),'Quickstart',
TRIM(SUBSTRING_INDEX(
S] =>
Quickstart for set up. 1. Register your
)
The last part it's returning seems to be correct:
Quickstart for set up. 1. Register your
But why is the query itself returned? Here's the php:
if (!$result = mysql_query($query)) send(mysql_error(),"e");
$hitArray=array();
while ($row=mysql_fetch_array($result, MYSQL_ASSOC) ) { $hitArray[]=$row; }
Thanks for taking a look.
It's not returning itself, it's the key in the array, try to assign an alias to the CONCAT_WS part:
SELECT
CONCAT_WS( ... ) as concatenated
FROM documents WHERE MATCH(document)
AGAINST('Quickstart' IN BOOLEAN MODE )

mysql_query error if single quotes used

I want to know why
$amzius_sql = "SELECT DISTINCT `Age` , SUBSTRING( Age, LOCATE( ' ', Age ) ) AS `AgePrefix` , SUBSTRING_INDEX( Age, ' ', 1 ) AS `AgeValue` FROM `suoPage` ORDER BY `AgePrefix` , `AgeValue` LIMIT 0 , 30";
$amzius_res = mysql_query($amzius_sql);
works flawlessly and this:
$amzius_sql = 'SELECT DISTINCT `Age` , SUBSTRING( Age, LOCATE( " ", Age ) ) AS `AgePrefix` , SUBSTRING_INDEX( Age, " ", 1 ) AS `AgeValue` FROM `suoPage` ORDER BY `AgePrefix` , `AgeValue` LIMIT 0 , 30';
$amzius_res = mysql_query($amzius_sql);
produces an error:
Unknown column ' ' in 'field list'
The only difference is quotes. If both queries are queried in phpMyAdmin - both work, but only the first one works if queried by mysql_query() in PHP
Here is the explaination:
The ANSI_QUOTES mode causes the server to interpret double-quoted
strings as identifiers. Consequently, when this mode is enabled,
string literals must be enclosed within single quotation marks. They
cannot be enclosed within double quotation marks.
Link