【发布时间】:2012-05-28 16:57:31
【问题描述】:
我有一个要为其创建索引视图的视图。经过大量的精力,我能够为视图放置 sql 查询,它看起来像这样 -
ALTER VIEW [dbo].[FriendBalances] WITH SCHEMABINDING as
WITH
trans (Amount,PaidBy,PaidFor, Id) AS
(SELECT Amount,userid AS PaidBy, PaidForUsers_FbUserId AS PaidFor, Id FROM dbo.Transactions
FULL JOIN dbo.TransactionUser ON dbo.Transactions.Id = dbo.TransactionUser.TransactionsPaidFor_Id),
bal (PaidBy,PaidFor,Balance) AS
(SELECT PaidBy,PaidFor, SUM( Amount/ transactionCounts.[_count]) AS Balance FROM trans
JOIN (SELECT Id,COUNT(*)AS _count FROM trans GROUP BY Id) AS transactionCounts ON trans.Id = transactionCounts.Id AND trans.PaidBy <> trans.PaidFor
GROUP BY trans.PaidBy,trans.PaidFor )
SELECT ISNULL(bal.PaidBy,bal2.PaidFor)AS PaidBy,ISNULL(bal.PaidFor,bal2.PaidBy)AS PaidFor,
ISNULL( bal.Balance,0)-ISNULL(bal2.Balance,0) AS Balance
FROM bal
left JOIN bal AS bal2 ON bal.PaidBy = bal2.PaidFor AND bal.PaidFor = bal2.Paidby
WHERE ISNULL( bal.Balance,0)>ISNULL(bal2.Balance,0)
FriendBalances 视图的示例数据 -
PaidBy PaidFor Balance
------ ------- -------
9990 9991 1000
9990 9992 2000
9990 9993 1000
9991 9993 1000
9991 9994 1000
主要是2个表的join。
Transactions-
CREATE TABLE [dbo].[Transactions](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Date] [datetime] NOT NULL,
[Amount] [float] NOT NULL,
[UserId] [bigint] NOT NULL,
[Remarks] [nvarchar](255) NULL,
[GroupFbGroupId] [bigint] NULL,
CONSTRAINT [PK_Transactions] PRIMARY KEY CLUSTERED
Transactions 表中的样本数据 -
Id Date Amount UserId Remarks GroupFbGroupId
-- ----------------------- ------ ------ -------------- --------------
1 2001-01-01 00:00:00.000 3000 9990 this is a test NULL
2 2001-01-01 00:00:00.000 3000 9990 this is a test NULL
3 2001-01-01 00:00:00.000 3000 9991 this is a test NULL
TransactionUsers -
CREATE TABLE [dbo].[TransactionUser](
[TransactionsPaidFor_Id] [bigint] NOT NULL,
[PaidForUsers_FbUserId] [bigint] NOT NULL
) ON [PRIMARY]
TransactionUser 表中的样本数据 -
TransactionsPaidFor_Id PaidForUsers_FbUserId
---------------------- ---------------------
1 9991
1 9992
1 9993
2 9990
2 9991
2 9992
3 9990
3 9993
3 9994
现在我无法创建视图,因为我的查询包含 cte(s)。我现在有哪些选择?
如果可以删除 cte,那么其他有助于创建索引视图的选项应该是什么。
这是错误信息 -
Msg 10137, Level 16, State 1, Line 1 Cannot create index on view "ShareBill.Test.Database.dbo.FriendBalances" because it references common table expression "trans". Views referencing common table expressions cannot be indexed. Consider not indexing the view, or removing the common table expression from the view definition.
概念: 交易主要包括:
- 已支付的金额
-
UserId支付该金额的用户 - 还有一些暂时不重要的信息。
TransactionUser table 是 Transaction 和 User Table 之间的映射。本质上,一笔交易可以在多人之间共享。因此,我们将其存储在此表中。
所以我们有一个交易,其中 1 人支付,其他人分享金额。因此,如果 A 为 B 支付 100 美元,那么 B 将欠 A 100 美元。同样,如果 B 为 A 支付 90 美元,那么 B 将只欠 A 10 美元。现在如果 A 为 A、b、c 支付 300 美元,这意味着 B 将欠 A 110 美元,C 欠 A 10 美元。
因此,在此特定视图中,我们汇总了 2 个用户之间已支付的有效金额(如果有),从而知道一个人欠另一个人多少钱。
【问题讨论】:
-
不能仅仅因为包含 CTE 的语句而从语句中创建视图,这对我来说是错误的。尝试创建视图时遇到什么错误?
-
我已经添加了错误信息。它指的是cte trans。
-
看起来还有其他几个绊脚石要使它成为索引视图,而不仅仅是删除 CTE。您能否发布一些表的示例数据(例如 20 行左右,最好是
INSERT语句)、视图的预期结果并解释结果? -
看过您的示例并再次查看您的查询 - 有太多事情发生,您将无法根据当前表创建索引视图 - 没有办法避免需要知道
TransactionUser中有多少行,这意味着某处有COUNT(*)- 但是您不允许 CTE(如您所知)或子查询,也不允许将一个索引视图基于另一个索引视图,因此无法使用结果COUNT(*)更进一步。如果我们重新设计基表,可能会有办法。我会考虑一下,如果这对你有用吗? -
达米安,那真的很有帮助!只是提醒一下我不想要的东西 - 我不想创建单独的表格,这实际上是视图的替代品。原因是,我将不得不担心编写和维护用于在 Transaction 表或 TransactionUser 表发生更改时更新此特定表的代码。
标签: sql-server views common-table-expression materialized