MI.Sarwar
MI.Sarwar

Reputation: 153

MYSQL SELECT statement inside CONCAT function

I was trying to do something like this in my very big select statement, this code snippet is from the SELECT part of the query

CONCAT((SELECT alias.`date` FROM alias WHERE id IN(latest_id)),'<-',GROUP_CONCAT(
`alias`.`date` ORDER BY `alias`.`date` DESC SEPARATOR '<-')) AS "date_chain"

but I am getting NULL in "date_chain" column. If I only write this

GROUP_CONCAT(
`alias`.`date` 
ORDER BY `alias`.`date` DESC SEPARATOR '<-') AS "date_chain"

It works.

But I want to concat the latest date in the start of this chain.

adding full SQL

SELECT latest_id,CONCAT((SELECT alias.`date`FROM alias WHERE id IN (latest_id)),'<-',
GROUP_CONCAT(
  `alias`.`date` 
  ORDER BY `alias`.`date` DESC SEPARATOR '<-'
)) AS "date_chain" FROM alias WHERE latest_id IS NOT NULL GROUP BY latest_id;

Kindly can someone help me what is missing in my first syntax? Thank you

Upvotes: 1

Views: 27431

Answers (1)

Kamil Gosciminski
Kamil Gosciminski

Reputation: 17147

When any value that's an arugment for CONCAT() function is NULL - the output of function evaluates to NULL. See manual for reference.

CONCAT() returns NULL if any argument is NULL.

Try CONCAT_WS() where you can also specify a separator.

CONCAT_WS() does not skip empty strings. However, it does skip any NULL values after the separator argument.

However, don't put NULL as separator - that would cause the result to yield NULL.

Edit after comments

We established that the reason for this was improper use of outer query column latest_id as a feed for inner SELECT.

  SELECT alias.`date`FROM alias WHERE id IN (latest_id)

was just comparing each id to latest_id from the same row, while the desired result was to compare it to column from outer SELECT block.

Query after changes should be

SELECT 
  latest_id,
  CONCAT(
    (SELECT alias.`date`FROM alias WHERE id IN (o.latest_id)),
    '<-',
    GROUP_CONCAT(
      `alias`.`date` ORDER BY `alias`.`date` DESC SEPARATOR '<-'
    )
  ) 
  AS "date_chain" 
FROM alias o
WHERE latest_id IS NOT NULL
GROUP BY latest_id;

Though your query gives you what you want it is not the best way to achieve this result. You should in most cases avoid using CONCAT() because of NULL values and your SELECT inside an outer SELECT block as a column feed would make the query run slow (it must compute values for every row).

Please consider the following code as better practice to get the same result

SELECT
  foo.latest_id,
  CONCAT_WS('<-', a.date, foo.group_concat) AS date_chain
FROM(
  SELECT  
    latest_id, 
    GROUP_CONCAT(date ORDER BY date DESC SEPARATOR '<-') AS group_concat
  FROM alias
  WHERE latest_id IS NOT NULL
  GROUP BY latest_id
) foo
LEFT JOIN alias a ON
  foo.latest_id = a.id

Upvotes: 5

Related Questions