mysql - 使用 IFNULL 和 CONCAT_WS returns 空字符串查询,而不是在 NULL 的情况下预定义的 IFNULL 参数
mysql - Query with IFNULL and CONCAT_WS returns empty string instead predefined IFNULL parameter in case of NULL
我正在使用子查询和 JOIN
s 处理复杂的 MySQL 查询,这是我的查询:
SELECT
id,
ancient_source_name,
ancient_source_name_alt,
ancient_source_type,
ancient_source_type_id,
IFNULL(IF(ancient_source_material = 'Unknown', NULL, ancient_source_material), '-') AS ancient_source_material,
ancient_source_year,
dynasty,
ancient_period,
author,
IFNULL(CONCAT_WS(', ',
IF(provenance_country = 'Unknown' OR provenance_country = 'Not Applicable', NULL, provenance_country),
IF(provenance_locality = 'Unknown' OR provenance_locality = 'Not Applicable', NULL, provenance_locality),
IF(provenance_place = 'Unknown' OR provenance_place = 'Not Applicable', NULL, provenance_place)
), '-') AS provenance_loc,
IFNULL(CONCAT_WS(', ',
IF(current_country = 'Unknown' OR current_country = 'Not Applicable', NULL, current_country),
IF(current_locality = 'Unknown' OR current_locality = 'Not Applicable', NULL, current_locality),
IF(current_place = 'Unknown' OR current_place = 'Not Applicable', NULL, current_place)
), '-') AS current_loc
FROM (
SELECT
hgn_ancient_sources.id AS id,
ancient_source_name,
IFNULL(ancient_source_name_alt, '-') AS ancient_source_name_alt,
IFNULL(ancient_source_year, '-') AS ancient_source_year,
ancient_source_type,
ancient_source_type_id,
ancient_source_material,
dynasty,
ancient_period,
provenance_countries.country AS provenance_country,
provenance_localities.locality AS provenance_locality,
provenance_places.place AS provenance_place,
current_countries.country AS current_country,
current_localities.locality AS current_locality,
current_places.place AS current_place,
IFNULL(author_name, '-') AS author
FROM hgn_ancient_sources
JOIN hgn_ancient_source_types ON hgn_ancient_sources.ancient_source_type_id = hgn_ancient_source_types.id
JOIN hgn_ancient_source_materials ON hgn_ancient_sources.ancient_source_material_id = hgn_ancient_source_materials.id
JOIN hgn_dynasties ON hgn_ancient_sources.ancient_source_dynasty_id = hgn_dynasties.id
JOIN hgn_ancient_periods ON hgn_ancient_sources.ancient_source_period_id = hgn_ancient_periods.id
LEFT JOIN junc_ancient_source_has_author ON hgn_ancient_sources.id = junc_ancient_source_has_author.ancient_source_id
LEFT JOIN hgn_authors ON junc_ancient_source_has_author.author_id = hgn_authors.id
JOIN junc_place_has_location AS provenance_place_has_location ON hgn_ancient_sources.ancient_source_provenance_place_id = provenance_place_has_location.id
JOIN junc_place_has_location AS current_place_has_location ON hgn_ancient_sources.ancient_source_current_place_id = current_place_has_location.id
JOIN junc_locality_has_country AS provenance_locality_has_country ON provenance_place_has_location.location_id = provenance_locality_has_country.id
JOIN junc_locality_has_country AS current_locality_has_country ON current_place_has_location.location_id = current_locality_has_country.id
JOIN hgn_places AS provenance_places ON provenance_place_has_location.place_id = provenance_places.id
JOIN hgn_places AS current_places ON current_place_has_location.place_id = current_places.id
JOIN hgn_localities AS provenance_localities ON provenance_locality_has_country.locality_id = provenance_localities.id
JOIN hgn_localities AS current_localities ON current_locality_has_country.locality_id = current_localities.id
JOIN hgn_countries AS provenance_countries ON provenance_locality_has_country.country_id = provenance_countries.id
JOIN hgn_countries AS current_countries ON current_locality_has_country.country_id = current_countries.id
) AS subquery
除这部分代码外一切正常:
IFNULL(CONCAT_WS(', ',
IF(provenance_country = 'Unknown' OR provenance_country = 'Not Applicable', NULL, provenance_country),
IF(provenance_locality = 'Unknown' OR provenance_locality = 'Not Applicable', NULL, provenance_locality),
IF(provenance_place = 'Unknown' OR provenance_place = 'Not Applicable', NULL, provenance_place)
), '-') AS provenance_loc,
IFNULL(CONCAT_WS(', ',
IF(current_country = 'Unknown' OR current_country = 'Not Applicable', NULL, current_country),
IF(current_locality = 'Unknown' OR current_locality = 'Not Applicable', NULL, current_locality),
IF(current_place = 'Unknown' OR current_place = 'Not Applicable', NULL, current_place)
), '-') AS current_loc
当有 1/3 或 2/3 列具有 Unknown
或 Not Applicable
值时,我得到了很好的结果,但是当 3/3 列(例如 current_country
,current_locality
, current_place
) 具有这两个值之一,结果我得到空单元格,而不是预期的 -
。
我尝试对代码进行不同的更改,但没有任何效果。我应该提到,例如,查询的这一部分:
IFNULL(IF(ancient_source_material = 'Unknown', NULL, ancient_source_material), '-') AS ancient_source_material
工作完美,所以我的假设是 CONCAT_WS()
功能有问题,但我找不到问题。
CONCAT_WS()
returns 如果非空分隔符后的所有参数都是 NULL
.
则为空字符串
参见 demo.
我没有发现 MySql's documentation (like it is made clear in SQL Server's documentation 中明确说明了这一点。
你可以做的是也使用 NULLIF()
检查结果是否为空字符串,并在使用 IFNULL()
:
之前将其更改为 NULL
IFNULL(NULLIF(CONCAT_WS(', ',
IF(provenance_country = 'Unknown' OR provenance_country = 'Not Applicable', NULL, provenance_country),
IF(provenance_locality = 'Unknown' OR provenance_locality = 'Not Applicable', NULL, provenance_locality),
IF(provenance_place = 'Unknown' OR provenance_place = 'Not Applicable', NULL, provenance_place)
), ''), '-') AS provenance_loc
参见demo。
我正在使用子查询和 JOIN
s 处理复杂的 MySQL 查询,这是我的查询:
SELECT
id,
ancient_source_name,
ancient_source_name_alt,
ancient_source_type,
ancient_source_type_id,
IFNULL(IF(ancient_source_material = 'Unknown', NULL, ancient_source_material), '-') AS ancient_source_material,
ancient_source_year,
dynasty,
ancient_period,
author,
IFNULL(CONCAT_WS(', ',
IF(provenance_country = 'Unknown' OR provenance_country = 'Not Applicable', NULL, provenance_country),
IF(provenance_locality = 'Unknown' OR provenance_locality = 'Not Applicable', NULL, provenance_locality),
IF(provenance_place = 'Unknown' OR provenance_place = 'Not Applicable', NULL, provenance_place)
), '-') AS provenance_loc,
IFNULL(CONCAT_WS(', ',
IF(current_country = 'Unknown' OR current_country = 'Not Applicable', NULL, current_country),
IF(current_locality = 'Unknown' OR current_locality = 'Not Applicable', NULL, current_locality),
IF(current_place = 'Unknown' OR current_place = 'Not Applicable', NULL, current_place)
), '-') AS current_loc
FROM (
SELECT
hgn_ancient_sources.id AS id,
ancient_source_name,
IFNULL(ancient_source_name_alt, '-') AS ancient_source_name_alt,
IFNULL(ancient_source_year, '-') AS ancient_source_year,
ancient_source_type,
ancient_source_type_id,
ancient_source_material,
dynasty,
ancient_period,
provenance_countries.country AS provenance_country,
provenance_localities.locality AS provenance_locality,
provenance_places.place AS provenance_place,
current_countries.country AS current_country,
current_localities.locality AS current_locality,
current_places.place AS current_place,
IFNULL(author_name, '-') AS author
FROM hgn_ancient_sources
JOIN hgn_ancient_source_types ON hgn_ancient_sources.ancient_source_type_id = hgn_ancient_source_types.id
JOIN hgn_ancient_source_materials ON hgn_ancient_sources.ancient_source_material_id = hgn_ancient_source_materials.id
JOIN hgn_dynasties ON hgn_ancient_sources.ancient_source_dynasty_id = hgn_dynasties.id
JOIN hgn_ancient_periods ON hgn_ancient_sources.ancient_source_period_id = hgn_ancient_periods.id
LEFT JOIN junc_ancient_source_has_author ON hgn_ancient_sources.id = junc_ancient_source_has_author.ancient_source_id
LEFT JOIN hgn_authors ON junc_ancient_source_has_author.author_id = hgn_authors.id
JOIN junc_place_has_location AS provenance_place_has_location ON hgn_ancient_sources.ancient_source_provenance_place_id = provenance_place_has_location.id
JOIN junc_place_has_location AS current_place_has_location ON hgn_ancient_sources.ancient_source_current_place_id = current_place_has_location.id
JOIN junc_locality_has_country AS provenance_locality_has_country ON provenance_place_has_location.location_id = provenance_locality_has_country.id
JOIN junc_locality_has_country AS current_locality_has_country ON current_place_has_location.location_id = current_locality_has_country.id
JOIN hgn_places AS provenance_places ON provenance_place_has_location.place_id = provenance_places.id
JOIN hgn_places AS current_places ON current_place_has_location.place_id = current_places.id
JOIN hgn_localities AS provenance_localities ON provenance_locality_has_country.locality_id = provenance_localities.id
JOIN hgn_localities AS current_localities ON current_locality_has_country.locality_id = current_localities.id
JOIN hgn_countries AS provenance_countries ON provenance_locality_has_country.country_id = provenance_countries.id
JOIN hgn_countries AS current_countries ON current_locality_has_country.country_id = current_countries.id
) AS subquery
除这部分代码外一切正常:
IFNULL(CONCAT_WS(', ',
IF(provenance_country = 'Unknown' OR provenance_country = 'Not Applicable', NULL, provenance_country),
IF(provenance_locality = 'Unknown' OR provenance_locality = 'Not Applicable', NULL, provenance_locality),
IF(provenance_place = 'Unknown' OR provenance_place = 'Not Applicable', NULL, provenance_place)
), '-') AS provenance_loc,
IFNULL(CONCAT_WS(', ',
IF(current_country = 'Unknown' OR current_country = 'Not Applicable', NULL, current_country),
IF(current_locality = 'Unknown' OR current_locality = 'Not Applicable', NULL, current_locality),
IF(current_place = 'Unknown' OR current_place = 'Not Applicable', NULL, current_place)
), '-') AS current_loc
当有 1/3 或 2/3 列具有 Unknown
或 Not Applicable
值时,我得到了很好的结果,但是当 3/3 列(例如 current_country
,current_locality
, current_place
) 具有这两个值之一,结果我得到空单元格,而不是预期的 -
。
我尝试对代码进行不同的更改,但没有任何效果。我应该提到,例如,查询的这一部分:
IFNULL(IF(ancient_source_material = 'Unknown', NULL, ancient_source_material), '-') AS ancient_source_material
工作完美,所以我的假设是 CONCAT_WS()
功能有问题,但我找不到问题。
CONCAT_WS()
returns 如果非空分隔符后的所有参数都是 NULL
.
则为空字符串
参见 demo.
我没有发现 MySql's documentation (like it is made clear in SQL Server's documentation 中明确说明了这一点。
你可以做的是也使用 NULLIF()
检查结果是否为空字符串,并在使用 IFNULL()
:
NULL
IFNULL(NULLIF(CONCAT_WS(', ',
IF(provenance_country = 'Unknown' OR provenance_country = 'Not Applicable', NULL, provenance_country),
IF(provenance_locality = 'Unknown' OR provenance_locality = 'Not Applicable', NULL, provenance_locality),
IF(provenance_place = 'Unknown' OR provenance_place = 'Not Applicable', NULL, provenance_place)
), ''), '-') AS provenance_loc
参见demo。