MySQL如何在不获取NULL的情况下将结果展平为一行

时间:2016-05-26 12:48:08

标签: mysql

我对MySQL查询非常陌生,无法弄清楚如何让数据看起来像我想要的那样。

我有三个表通常看起来像这样但有更多数据,最终查询不会受到我在这里的一个主机名的限制。我只是想简化它。

infrastructure_server表

id | hostname
1    ld0007

infrastructure_server_jobs表

server_id  |  job_id
1             1
1             2

jobs_job表

id  |  end_date
1      2015-12-21 09:51:56
2      2016-01-27 10:02:36

这是我的问题:

SELECT
    CASE WHEN type = "provision" THEN CAST(end_date AS DATE) END AS ProvDate,
    CASE WHEN type = "decom" THEN CAST(end_date AS DATE) END AS DecomDate,
    infserver.hostname as HostName

FROM 
    infrastructure_server infserver

inner join infrastructure_server_jobs sj on infserver.id = sj.server_id
inner join jobs_job jj on sj.job_id = jj.id

where
infserver.status != "PROVFAILED"
AND
infserver.group_id ="2"
AND
infserver.hostname ="ld0007"

我的结果是:

ProvDate, DecomDate, HostName
'2015-12-21', NULL, 'ld0007'
NULL, '2016-01-27', 'ld0007'

如果我按HostName添加一个组,那么它会将其展平为一行但我丢失了DecomDate:

ProvDate, DecomDate, HostName
'2015-12-21', NULL, 'ld0007'

我需要的结果是每个主机名一行:

ProvDate, DecomDate, HostName
'2015-12-21', '2016-01-27', 'ld0007'

Thorsten,列类型位于jobs_job表中。我正在使用的工具是MySQl Workbench。如果我在没有MAX()的情况下运行查询(在原始文章中删除了infserver.hostname ='ld0007',这里有一些我得到的行

ProvDate, DecomDate, HostName
'2016-01-28', NULL, 'ld0043'
NULL, '2016-01-29', 'ld0043'
'2016-01-28', NULL, 'ld0044'
NULL, '2016-03-30', 'ld0044'
'2016-01-28', NULL, 'ld0045'
NULL, '2016-03-30', 'ld0045'
'2016-01-28', NULL, 'ld0046'
NULL, '2016-01-28', 'ld0046'
'2016-01-28', NULL, 'ld0047'
NULL, '2016-01-29', 'ld0047'
'2016-01-29', NULL, 'ld0048'
NULL, '2016-03-14', 'ld0048'
'2016-01-29', NULL, 'ld0049'
NULL, '2016-02-09', 'ld0049'
'2016-01-29', NULL, 'ld0050'
NULL, '2016-03-31', 'ld0050'
'2016-01-29', NULL, 'ld0051'
NULL, '2016-01-29', 'ld0051'
'2016-01-29', NULL, 'ld0052'
NULL, '2016-01-29', 'ld0052'
'2016-01-29', NULL, 'ld0053'
NULL, '2016-01-29', 'ld0053'

如果我添加一个计数器,我总共得到了1989行。当我添加MAX()时,我只返回一条记录

SET @counter = 0;
SELECT
    (@counter:= @counter + 1) as counter,
    CASE WHEN type = "provision" THEN CAST(end_date  AS DATE) END AS ProvDate,
    CASE WHEN type = "decom" THEN CAST(end_date AS DATE) END AS DecomDate,
    infserver.hostname as HostName
FROM 
    infrastructure_server infserver
inner join infrastructure_server_jobs sj on infserver.id = sj.server_id
inner join jobs_job jj on sj.job_id = jj.id
where
infserver.status != "PROVFAILED"
AND
infserver.group_id ="2"

1 个答案:

答案 0 :(得分:0)

按主机名分组时,每个主机名会得到一个结果行。例如,如果选择ProvDate,则会得到一个ProvDate - 只要您没有指定。因此,使用诸如MAX之类的聚合函数来说明您想要获得哪一个。并且当MAX忽略空值时,这甚至可以解决您的整个问题: - )

SELECT
  MAX(CASE WHEN type = 'provision' THEN CAST(end_date AS DATE) END) AS ProvDate,
  MAX(CASE WHEN type = 'decom' THEN CAST(end_date AS DATE) END) AS DecomDate,
  infserver.hostname as HostName
FROM infrastructure_server infserver
INNER JOIN infrastructure_server_jobs sj on infserver.id = sj.server_id
INNER JOIN jobs_job jj on sj.job_id = jj.id
where infserver.status <> 'PROVFAILED'
AND infserver.group_id = 2
AND infserver.hostname = 'ld0007'
group by infserver.hostname;