SQL Server:从 2 个表创建视图

Posted

技术标签:

【中文标题】SQL Server:从 2 个表创建视图【英文标题】:SQL Server : creating a view from 2 tables 【发布时间】:2016-08-22 15:20:09 【问题描述】:

我有两张桌子,一张有料斗和里面的配料(每天记录一次或在更换配料时记录)

例子:

Hoppers |  Ingredients  |   Timestamp
--------+---------------+----------------------
Hop_1   |  Ing_A        |   8/22/2016 06:00:00
Hop_2   |  Ing_B        |   8/22/2016 06:00:00

等等……

我还有第二张表,其中记录了每个漏斗每小时使用的总数

例子:

Name               |   Value  |   Timestamp
-------------------+----------+---------------------
Hop_1 Daily Total  |  100     |   8/22/2016 11:00:00
Hop_1 Run Total    |   30     |   8/22/2016 11:00:00

等等……

我想创建一个视图,显示每个料斗的产量并说出名称。

例子:

Hop_1 Ingredient | Hop_1 Daily | Hop_1 Run | Timestamp  
-----------------+-------------+-----------+-------------------
Ing_A            |      100    |      30   | 8/22/2016 11:00:00  

对不起,如果它看起来不太好,我是格式化新手

【问题讨论】:

所以除了切割名称列的第一部分之外,没有任何列可以连接 2 个表?如果有超过 1 种成分,您将如何确定哪种价值与哪种成分对应?如果您想要一个具有特定于料斗的列名称的枢轴,当存在超过 1 个料斗时您会怎么做?添加其他列? 是的,决赛桌将是所有漏斗,以及所有每日总数,等等。我只是不想全部输入...我希望我能以某种方式按时间戳对它们进行分组从每个表...但是时间戳不会彼此相等,我的想法是加载每日总计的值并运行总计,然后使用该时间戳然后在另一个表中查找最新的时间戳。我只是不确定如何做到这一点。我尝试这样做的原因是因为我只是想在以前创建的数据库中组织信息 很抱歉尼尔您的评论没有解决我的问题,也许我没有很好地说明它们。 1)您如何在表格之间建立联系?那么如果有超过 1 种成分,你怎么知道 Ing_A 会达到价值呢? 2) 料斗将如何在决赛桌中表示,每个料斗的附加列?您在网站上没有得到太多关注,可能是因为您的问题没有回答一些未知数,也因为您没有表现出试图获得您想要的东西,即使这种尝试已经遥遥无期 1.表之间的关系,当料斗中的成分发生变化时,运行总数重置为 0。(并且新成分使用时间戳输入数据库)所以我应该根据时间戳知道。如果在上午 11:30 运行总数为 500,我可以查看 Ingredeint where Ingredients.Timestamp 2.在最终表格中,它们将是 Hopper1 成分、Hopper1 运行总计、Hopper1 每日总计、Hopper2 成分、Hopper2 运行总计、Hopper2 每日总计的列。 【参考方案1】:

为了记录,我真的不认为结构是最好的主意,因为它需要动态 sql 通过几个循环和大量的 LEFT SELF JOINS 来实现它。但是给你:

IF OBJECT_ID('tempdb..#Ingredients') IS NOT NULL
    BEGIN
        DROP TABLE #Ingredients
    END

IF OBJECT_ID('tempdb..#Totals') IS NOT NULL
    BEGIN
        DROP TABLE #Totals
    END

CREATE TABLE #Ingredients (Hoppers VARCHAR(25), Ingredeients VARCHAR(25), [Timestamp] DATETIME)
CREATE TABLE #Totals (Name VARCHAR(50), Value INT, [Timestamp] DATETIME)

INSERT INTO #Ingredients (Hoppers, Ingredeients, [Timestamp])
VALUES ('Hop_1','Ing_A','8/22/2016 06:00:00'),('Hop_2','Ing_B','8/22/2016 06:00:00'),('Hop_3','Ing_C','8/22/2016 06:00:00')
INSERT INTO #Totals (Name, Value, [Timestamp])
VALUES ('Hop_1 Daily Total',100,'8/22/2016 11:00:00'),('Hop_1 Run Total',30,'8/22/2016 11:00:00'),('Hop_1 Run Total',60,'8/22/2016 09:00:00')
,('Hop_2 Daily Total',500,'8/22/2016 11:00:00'),('Hop_2 Run Total',10,'8/22/2016 11:00:00'),('Hop_2 Run Total',5,'8/22/2016 10:00:00')
,('Hop_3 Daily Total',400,'8/22/2016 11:00:00'),('Hop_3 Run Total',85,'8/22/2016 11:00:00'),('Hop_3 Run Total',65,'8/22/2016 10:00:00')


DECLARE @HopperCount INT
SELECT @HopperCount = COUNT(DISTINCT i.Hoppers)
FROM
    #Ingredients i
    INNER JOIN #Totals t
    ON t.Name LIKE i.Hoppers + '%'


DECLARE @I INT = 1
DECLARE @Sql NVARCHAR(MAX)

SET @Sql = '
;WITH cte AS (
    SELECT
       i.Hoppers
       ,i.Ingredeients
       ,Value
       ,t.[Timestamp]
       ,CASE WHEN t.Name LIKE ''%Daily%'' THEN 1 ELSE 0 END as IsDaily
       ,ROW_NUMBER() OVER (PARTITION BY i.Hoppers, t.name ORDER BY t.[Timestamp] DESC) as RunRowNum
       ,DENSE_RANK() OVER (PARTITION BY 1 ORDER BY i.Hoppers) as HooperNumber
    FROM
       #Ingredients i
       INNER JOIN #Totals t
       ON t.Name LIKE i.Hoppers + ''%''
       AND i.[Timestamp] <= t.[Timestamp]
)

SELECT
    c.Ingredeients AS [Hop_' + CAST(@I AS VARCHAR(10)) + ' Ingredient]
    ,SUM(CASE WHEN c.IsDaily = 1 THEN c.Value END) AS [Hop_' + CAST(@I AS VARCHAR(10)) + ' Daily]
    ,SUM(CASE WHEN c.IsDaily = 0 THEN c.Value END) AS [Hop_' + CAST(@I AS VARCHAR(10)) + ' Run]
    ,MAX(c.[Timestamp]) AS [Hop_' + CAST(@I AS VARCHAR(10)) + ' Timestamp] '


SET @I = 2
WHILE @I <= ISNULL(@HopperCount,0)
BEGIN
    SET @Sql = @Sql + '
    ,c'+ CAST(@I AS VARCHAR(10)) +  '.Ingredeients AS [Hop_' + CAST(@I AS VARCHAR(10)) + ' Ingredient]
    ,SUM(CASE WHEN c'+ CAST(@I AS VARCHAR(10)) + '.IsDaily = 1 THEN c' + CAST(@I AS VARCHAR(10)) + '.Value END) AS [Hop_' + CAST(@I AS VARCHAR(10)) + ' Daily]
    ,SUM(CASE WHEN c' + CAST(@I AS VARCHAR(10)) + '.IsDaily = 0 THEN c' + CAST(@I AS VARCHAR(10))+ '.Value END) AS [Hop_' + CAST(@I AS VARCHAR(10)) + ' Run]
    ,MAX(c' + CAST(@I AS VARCHAR(10)) + '.[Timestamp]) AS [Hop_' + CAST(@I AS VARCHAR(10)) + ' Timestamp] '

    SET @I = @I + 1
END


SET @Sql = @Sql + '
FROM
    cte c '


SET @I = 2
WHILE @I <= ISNULL(@HopperCount,0)
BEGIN
    SET @Sql = @Sql + '
    LEFT JOIN cte c' + CAST(@I AS VARCHAR(10)) + ' 
    ON c.HooperNumber + ' + CAST(@I - 1 AS VARCHAR(10)) + ' = c' + CAST(@I AS VARCHAR(10)) + '.HooperNumber 
    AND c' + CAST(@I AS VARCHAR(10))+ '.RunRowNum = 1
    AND c.IsDaily = c' + CAST(@I AS VARCHAR(10)) + '.IsDaily '

    SET @I = @I + 1
END

SET @Sql = @Sql + '
WHERE
    c.HooperNumber = 1
    AND c.RunRowNum = 1
GROUP BY
    c.Ingredeients
'

SET @I = 2
WHILE @I <= ISNULL(@HopperCount,0)
BEGIN
    SET @Sql = @Sql + ',c' + CAST(@I AS VARCHAR(10)) + '.Ingredeients
    '

    SET @I = @I + 1
END

EXECUTE (@sql)

【讨论】:

【参考方案2】:

您可以根据需要使用数据透视表。 这是一个链接:https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

【讨论】:

以上是关于SQL Server:从 2 个表创建视图的主要内容,如果未能解决你的问题,请参考以下文章

SQL从3个表创建视图

调整SQL Server中的大型查询

用sqlserver2008创建了1个表,里面有几个属性,其中一个属性我不想要了,怎么删除,

SQL Server创建视图——视图的作用

视图中四个表的 SQL Server 条件连接

从视图填充或创建表的 SQL Server 过程 - 性能问题