【问题标题】:Removing Nulls and Fixing Alignment删除空值并修复对齐
【发布时间】:2020-08-26 11:50:00
【问题描述】:

我正在使用 SQL Server,并使用 SMSS 进行查询。我不是一个全职的 SQL 用户,我正在尝试为我们的工作人员制作一些仪表板,使用 SQL 作为数据收集器,并使用下面的查询。

查询几乎可以正常工作,但我需要将所有结果放入成对的行中,而不是显示空值。这是我写的查询:

SELECT convert(varchar(11), start_time, 103) AS Date, DATENAME(weekday, start_time) AS Week_Day,
CASE WHEN CAST(start_time AS time) = '05:00:00'
THEN name
END AS 'Morning',
CASE WHEN CAST(start_time AS time) ='12:59:59'
THEN name
END AS 'Afternoon',
CASE WHEN CAST(start_time AS time) = '20:59:59'
THEN name
END AS 'Evening'
FROM [somedb].[dbo].[tb_some_table]
WHERE [start_time] >= dateadd(day, 2-datepart(dw, getdate()), CONVERT(date,getdate()))
AND [start_time] < dateadd(day, 9-datepart(dw, getdate()), CONVERT(date,getdate()))

这给了我这样的结果:

Date       Week_Day Morning Afternoon Evening
24/08/2020 Monday   Fred    NULL      NULL
24/08/2020 Monday   Markus  NULL      NULL
24/08/2020 Monday   NULL    Chuck     NULL
24/08/2020 Monday   NULL    Bill      NULL
24/08/2020 Monday   NULL    NULL      John
24/08/2020 Monday   NULL    NULL      Wayne

但是,我想得到这个:

Date       Week_Day Morning Afternoon Evening
24/08/2020 Monday   Fred    Chuck     John
24/08/2020 Monday   Markus  Bill      Wayne

谁能帮帮我? :/

编辑:数据如下所示:

如果我运行一个选择,数据看起来像这样:

start_time              end_time                name

2020-08-24 05:00:00.000 2020-08-24 12:59:59.000 Frank
2020-08-24 05:00:00.000 2020-08-24 12:59:59.000 Markus
2020-08-24 12:59:59.000 2020-08-24 20:59:59.000 Chuck
2020-08-24 12:59:59.000 2020-08-24 20:59:59.000 Bill
2020-08-24 20:59:59.000 2020-08-25 05:00:00.000 John
2020-08-24 20:59:59.000 2020-08-25 05:00:00.000 Wayne

【问题讨论】:

  • Fred 与 Chuck 和 John 以及 Markus 与 Bill 和 Wayne 有什么关系?例如,为什么不是 Fred、Bill 和 John?
  • 另外,您的数据您不想要的结果之前是什么样子的?
  • 嗨,Frank 和 Markus 周一早上一起工作,Chuck 和 Bill 周一下午一起工作,Jpn 和 Wayne 周一晚上一起工作。
  • 这与 Fred 和 Chuck 之间的关系有什么关系?他们在同一排,为什么他们在一起?正如我所问的,为什么不是 Fred 和 Bill?
  • Edit 你的问题,不要在 cmets 中转储。

标签: sql sql-server smss


【解决方案1】:

我想你想要聚合:

SELECT CONVERT(DATE, start_time) as date,
       DATENAME(weekday, MIN(start_time)) AS Week_Day,
       MAX(CASE WHEN CAST(start_time AS time) = '05:00:00' THEN name END) AS Morning,
       MAX(CASE WHEN CAST(start_time AS time) = '12:59:59' THEN name END) AS Afternoon,
       MAX(CASE WHEN CAST(start_time AS time) = '20:59:59' THEN name END) AS Evening
FROM (SELECT t.*,
             ROW_NUMBER() OVER (PARTITION BY start_time ORDER BY start_time) as seqnum
      FROM [somedb].[dbo].[tb_some_table] t
      WHERE start_time >= dateadd(day, 2-datepart(dw, getdate()), CONVERT(date, getdate())) AND
            start_time < dateadd(day, 9-datepart(dw, getdate()), CONVERT(date, getdate()))
     ) t
GROUP BY CONVERT(DATE, start_time), seqnum;

请注意,您需要每个日期多行。 ROW_NUMBER() 正在确定这一点。

注意事项:

  • 您无需将日期转换为字符串即可提取日期组件。仅当您确实需要特定格式的日期时才使用 convert()
  • 时间是准确的似乎很奇怪。我希望范围。如果真的是这样,那就问一个新问题。它会改变查询。
  • 仅对字符串和日期常量使用单引号。不要将它们用于列名 - 当(有一天)您认为您使用单引号引用列时,这只会导致难以调试的错误。

【讨论】:

  • 像往常一样,对我来说太快了......恭喜你达到了 1000K :-)
  • 感谢您如此快速的回复和所有的指点,非常感谢。我还在学习 SQL,查询是一个充满 Goolging 的早晨的结果,所以我非常感谢你的帮助。运行查询时,我收到以下错误,消息 107,级别 15,状态 1,第 39 行列前缀“t”与查询中使用的表名或别名不匹配。消息 8155,级别 16,状态 2,第 45 行没有为“t”的第 1 列指定列名。 “t”代表什么?
  • 这里需要在GROUP BY中添加DATENAME(weekday, start_time),或者在SELECT中改成DATENAME(weekday, CONVERT(date,start_time))
  • t 是 Gordon 使用的别名,@G-Man83。别名是 SQL 的一个非常基本的部分,使用 good 别名是非常好的做法。
猜你喜欢
  • 2023-03-07
  • 2023-02-15
  • 2018-01-23
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
  • 1970-01-01
  • 2023-01-19
  • 1970-01-01
相关资源
最近更新 更多