从详细信息表创建“摘要”列

时间:2012-01-17 15:40:27

标签: sql sql-server sql-server-2008

我的应用程序有多个stores,每个商店在store_hours中都有多条记录。

store_hours表如下所示:

store_id [int]
day [varchar(20)]
opening_time [varchar(20)]
closing_time [varchar(20)]

并且一家商店的记录可能如下所示:

301, 'Monday', '7am', '8:30pm'
301, 'Tuesday', '7am', '8:30pm'
301, 'Wednesday', '7am', '8:30pm'
301, 'Thursday', '7am', '8:30pm'
301, 'Friday', '7am', '10pm'
301, 'Saturday', 'closed,' 'closed'
301, 'Sunday', 'closed,' 'closed'

我们正在尝试在商店桌上创建“小时摘要”列。以上查询将导致类似“M:7:00-8:00,T:7 am-8:30pm,W:7 am-8:30pm,T:7 am-8:30pm,F:7 am-8:30pm,S :关闭,S:关闭'

我通过运行类似于此的查询来填充它:

UPDATE s
SET hours_summary = 
'M: ' + (SELECT TOP 1 ch.opening_time FROM store_hours ch WHERE c.id = ch.store AND [day] = 'Monday') + '-' + (SELECT TOP 1 ch.closing_time FROM store_hours ch WHERE c.id = ch.store AND [day] = 'Monday') + ', ' +
'T: ' + (SELECT TOP 1 ch.opening_time FROM store_hours ch WHERE c.id = ch.store AND [day] = 'Tuesday') + '-' + (SELECT TOP 1 ch.closing_time FROM store_hours ch WHERE c.id = ch.store AND [day] = 'Tuesday') + ', '
    (etc, for the other five days)
FROM stores s

现在,这将有效(或多或少),但我有几个问题。

  1. 在我看来,这很难看,似乎有很多重复。无论如何你有没有想过要改进它?
  2. 对于某些记录,如果商店已关闭,则store_hours表中根本没有记录。我还没有找到一个好方法来处理这个问题。建议?
  3. 修改

    有些人建议使用数据透视表。我知道如何在那里获得开放的关闭时间,但我看不出我如何做到这两点,而且我看不出如何将它汇总到一个查询中。

    这是我到目前为止所做的:

    SELECT centre, [Monday], [Tuesday], [Wednesday], [Thursday], [Friday], [Saturday], [Sunday]
    FROM (SELECT centre, [day], opening_time FROM centre_hours) AS p
    PIVOT (MAX(opening_time) FOR [day] IN ([Monday], [Tuesday], [Wednesday], [Thursday], [Friday], [Saturday], [Sunday])) AS pt
    

    再次编辑

    对于那些来自未来想知道我是否/如何解决这个问题的人,我最终创建了两个单独的数据透视表,然后插入第一个表的结果,并使用第二个表的结果进行UPDATEing。

3 个答案:

答案 0 :(得分:2)

也许这会对你有所帮助。没有更新或插入。与原始帖子相同的表格

DECLARE @store_hours TABLE
(
    store_id int,
    [day] varchar(20),
    opening_time varchar(20),
    closing_time varchar(20)
)

INSERT INTO @store_hours(store_id,[day],opening_time,closing_time)VALUES(301, 'Monday', '7am', '8:30pm')
INSERT INTO @store_hours(store_id,[day],opening_time,closing_time)VALUES(301, 'Tuesday', '7am', '8:30pm')
INSERT INTO @store_hours(store_id,[day],opening_time,closing_time)VALUES(301, 'Wednesday', '7am', '8:30pm')
INSERT INTO @store_hours(store_id,[day],opening_time,closing_time)VALUES(301, 'Thursday', '7am', '8:30pm')
INSERT INTO @store_hours(store_id,[day],opening_time,closing_time)VALUES(301, 'Friday', '7am', '10pm')
INSERT INTO @store_hours(store_id,[day],opening_time,closing_time)VALUES(301, 'Saturday', 'closed', 'closed')
INSERT INTO @store_hours(store_id,[day],opening_time,closing_time)VALUES(301, 'Sunday', 'closed' ,'closed')

SELECT
    *
FROM
(
    SELECT 
        [day], 
        opening_time+'-'+closing_time AS Times
    FROM @store_hours AS store_hours
) AS SourceTable
PIVOT
    (
        MAX(Times)
        FOR [day] IN ([Monday], [Tuesday], [Wednesday], [Thursday], [Friday], [Saturday],[Sunday])
    )AS PivotTable;

答案 1 :(得分:1)

我实际上会转动数据并使列标题显示带有时间的日期。 请参阅pivot help http://msdn.microsoft.com/en-us/library/ms177410.aspx

答案 2 :(得分:1)

在不知道更多情况的情况下,很难判断store_hours架构在这种情况下是否正确。你可以设计开放时间的模式有点不同 - 通常认为你每天有一行是正确的 - 这是一种默认的设计模式。

这是您可以选择在模式中透视列以使生活更轻松的固定方案之一。 (取决于其他什么用途,可能会变得更难,所以这里有一个警告取决于你的用法。)

store_id [int] 
week_begin_dt [datetime]
mon_opening_time [varchar(20)] 
mon_closing_time [varchar(20)] 
tue_opening_time [varchar(20)] 
tue_closing_time [varchar(20)] 
...
sun_opening_time [varchar(20)] 
sun_closing_time [varchar(20)] 

无论解决方案如何,我还会在商店营业时间内包含一个有效的开始日期,因为随着时间的推移它们会发生变化,因此您希望能够对数据进行时间分段。这将让您考虑将来的商店营业时间,而不仅仅是当前周的当前营业时间。 (假期和高峰期通常会改变营业时间。)