我正在尝试在MSSQL中创建一个已保存的视图,该视图返回已接受的提案列表。我遇到的问题是,如果提案有多个版本,它会将所有行返回为已接受,即使它实际上只是最新版本有效。
每个提案记录的报价ID不同,但报价编号和名称相同。确定我们想要返回哪个Quote ID记录的方法是具有最新版本号的提案。只有少数引号具有版本号,大多数引号都是唯一的。
我不知道我是否可以通过分组数据来实现这一目标,因为我想收集许多字段(除了下面列出的字段),其中主要包含文本。
以下是我所指的数据格式的示例
Quote ID | Quote Number | Quote Name | Version |
i3hfkdkj | 101 | John Smith Residence | 1 |
fheifjdh | 102 | Big Apple Food Service | 1 |
kdjfnf98 | 103 | Starbucks Coffee | 1 |
3498fhkd | 101 | John Smith Residence | 2 |
jfh3bfi3 | 104 | Susan Jane Apartment | 1 |
9834jfkd | 101 | John Smith Residence | 3 |
理想情况下,我希望查询只返回以下行
fheifjdh | 102 | Big Apple Food Service | 1 |
kdjfnf98 | 103 | Starbucks Coffee | 1 |
jfh3bfi3 | 104 | Susan Jane Apartment | 1 |
9834jfkd | 101 | John Smith Residence | 3 |
非常感谢您的帮助
丹
以下是我当前保存的视图的语法,该视图正常工作,但上面列出的内容除外。
SELECT
dbo.Quote_Main.quote_readable_id,
dbo.Quote_Main.quote_name,
dbo.Quote_Main.account_name,
dbo.Quote_Main.contact_name,
dbo.Quote_Main.quote_status,
dbo.Quote_Main.delivered_date,
dbo.Quote_Customers.first_name,
dbo.Quote_Customers.last_name,
dbo.Quote_Customers.customer_source,
dbo.Quote_Main.idCRM_opportunity,
dbo.Quote_Main.idQuote_Main,
dbo.Quote_Items.item_notes_html AS QuoteScope,
dbo.Quote_Items.item_notes,
dbo.Quote_Main.version
FROM
dbo.Quote_Items
LEFT JOIN dbo.Quote_Main ON dbo.Quote_Items.idQuote_Main = dbo.Quote_Main.idQuote_Main
LEFT JOIN dbo.Quote_Customers ON dbo.Quote_Main.idQuote_Main = dbo.Quote_Customers.idQuote_Main
WHERE
dbo.Quote_Items.long_description = 'Proposal Scope' AND
dbo.Quote_Main.quote_status = 'Won' AND
dbo.Quote_Customers.usage_type = 'Quote To'
答案 0 :(得分:2)
一种方法是使用not exists
:
select p.*
from proposals p
where not exists (select 1
from proposals p2
where p2.QuoteNumber = p.QuoteNumber and p2.version > p.version
);
您没有指定您正在使用的数据库,这应该基本上适用于视图的所有数据库。
编辑:
只需使用CTE:
with proposals as (
<your query here>
)
select p.*
from proposals p
where not exists (select 1
from proposals p2
where p2.QuoteNumber = p.QuoteNumber and p2.version > p.version
);
我会首先运行它以查看它是否具有合理的性能。如果没有,可能存在优化的余地。
答案 1 :(得分:1)
如果您使用的是SQL Server,则可以使用row_number()
:
select *
from (
select *,
row_number() over (partition by [Quote Number] order by Version desc) [rn]
from Quotes
) x
where x.rn=1
这会为每一行分配一个数字 - 该数字按版本排序(降序),并为每个报价编号重置。子查询的结果如下所示:
Quote ID | Quote# | Quote Name | Version | rn |
i3hfkdkj | 101 | John Smith Residence | 1 | 3 |
fheifjdh | 102 | Big Apple Food Service | 1 | 1 |
kdjfnf98 | 103 | Starbucks Coffee | 1 | 1 |
3498fhkd | 101 | John Smith Residence | 2 | 2 |
jfh3bfi3 | 104 | Susan Jane Apartment | 1 | 1 |
9834jfkd | 101 | John Smith Residence | 3 | 1 |
然后我们只是过滤rn=1
。
子查询是必要的,因为row_number()
不能直接在where
子句中使用。
答案 2 :(得分:1)
根据要求,这是一个应用于答案中添加的查询的后续示例。
此查询的整体结构已从原来的更改中通过移动表dbo.Quote_Main向上优先,相反dbo.Quote_Items向下。
SELECT
QM.quote_readable_id
, QM.quote_name
, QM.account_name
, QM.contact_name
, QM.quote_status
, QM.delivered_date
, QC.first_name
, QC.last_name
, QC.customer_source
, QM.idCRM_opportunity
, QM.idQuote_Main
, QI.item_notes_html AS QuoteScope
, QI.item_notes
, QM.version
FROM dbo.Quote_Main QM
INNER JOIN dbo.Quote_Customers
ON QM.idQuote_Main = QC.idQuote_Main
LEFT OUTER JOIN (
SELECT
idQuote_Main
, item_notes_html
, item_notes
-- note 1
, ROW_NUMBER() OVER (PARTITION BY idQuote_Main
ORDER BY qi_version DESC) AS RN
-- note 2
WHERE long_description = 'Proposal Scope'
FROM dbo.Quote_Items
) QI
ON QM.idQuote_Main = QI.idQuote_Main
AND QI.RN = 1
WHERE QM.quote_status = 'Won'
AND QC.usage_type = 'Quote To'
;
qi_version
,使用正确的字段答案 3 :(得分:-1)
只是堆积了一点
select quoteid,quotenum,quotename,ver from quotes q
where quotenum||ver = (select max(quotenum||ver) from quotes q2
where q.quotenum=q2.quotenum)