我總是喜歡創建一個玩具表和/或數據庫來展示我的想法。下面是一個這樣的片段。
以下是關於您的解決方案與我的解決方案的一些評論。
1 - 當您在開始時使用通配符將列與模式進行比較時,查詢優化器無法使用任何索引。因此,這會導致全表掃描。
2 - 我總是喜歡測試空值。合併是將空字符串默認爲空字符串的好方法。
3 - 如果您爲where邏輯使用持久計算列,則在插入或更新記錄時將其存儲在數據庫中。
4 - 持久計算列可以有一個索引,因此可以消除大表的表掃描。
我不得不使用查詢索引提示,因爲對於小表而言,表掃描速度更快。
此外,您可能需要添加member_fk和/或begin_date。 IE - 更多的工作/測試爲一個真實的生活的例子。
5 - 最後但並非最不重要,使用窗口分區和row_number()函數來查找最新的行。
因爲您不能在WHERE子句中的SELECT語句部分中引用計算,所以我將它綁定到CTE中。
有一些很好的概念在這裏:
- 通配符模式搜索等於全表掃描空值
- alwaystest /帳戶
- 持久化計算的列的索引 速度
- 使用分組功能進行挑選頂部結果
如果您有任何問題,只需填寫。
真誠
約翰
-- Drop old table
if object_id('tempdb.dbo.contracts') > 0
drop table tempdb.dbo.contracts;
go
-- Create new table
create table tempdb.dbo.contracts
(
id_num int identity(1,1),
member_fk int,
main_flag bit,
begin_date smalldatetime,
end_date smalldatetime,
description_txt varchar(512),
do_not_use_flag as
(
-- must have these words
(
case
when lower(coalesce(description_txt, '')) like '%gold%' then 0
when lower(coalesce(description_txt, '')) like '%silver%' then 0
when lower(coalesce(description_txt, '')) like '%bronze%' then 0
when lower(coalesce(description_txt, '')) like '%executive%' then 0
else 1
end
)
+
-- must not have these words
(
case
when lower(coalesce(description_txt, '')) like '%mitarbeiter%' then 1
when lower(coalesce(description_txt, '')) like '%kind%' then 1
when lower(coalesce(description_txt, '')) like '%teen%' then 1
when lower(coalesce(description_txt, '')) like '%kid%' then 1
else 0
end
)
+
-- must have begin_date <= end_date
(
case
when begin_date is null then 1
when end_date is null then 0
when begin_date <= end_date then 0
else 1
end
)
+
(
-- toss out non-main records
case
when main_flag = 1 then 0
else 1
end
)
) persisted
);
go
-- add index on id include flag
create nonclustered index ix_contracts
on tempdb.dbo.contracts (do_not_use_flag);
go
-- add data to table
insert into tempdb.dbo.contracts (member_fk, main_flag, begin_date, end_date, description_txt)
values
-- shows up
(1, 1, getdate() - 5, getdate(), 'Silver - good contract for DBA'),
-- main contract <> 1
(1, 0, getdate() - 5, getdate(), 'Gold - good contract for DBA'),
-- no flag = true
(1, 1, getdate() - 5, getdate(), 'Bronze - good contract for Teen'),
-- end < begin
(1, 1, getdate(), getdate()-5, 'Bronze - good contract for DBA'),
(2, 1, getdate() - 5, getdate(), 'Executive - good contract for DBA');
go
-- wait 5 seconds
WAITFOR DELAY '00:00:02';
go
insert into tempdb.dbo.contracts (member_fk, main_flag, begin_date, end_date, description_txt)
values
(2, 1, getdate() - 4, getdate(), 'Executive - good contract for DBA');
go
-- show the raw data
select * from tempdb.dbo.contracts as c
go
-- show the data
;
with cte_contract_by_recent_begin_dte
as
(
select
ROW_NUMBER() OVER (PARTITION BY member_fk ORDER BY begin_date desc) as top_id,
*
from
tempdb.dbo.contracts as c with(index(ix_contracts))
where
c.do_not_use_flag = 0
)
select * from cte_contract_by_recent_begin_dte as cte where cte.top_id = 1
從合同爲V1 WHERE (V1.Description LIKE '%%金' OR V1.Description LIKE '%西爾伯%' 或V1選擇V1.Contractbegin例如'%Bronze%' 或V1.Description like'%Executive%'ORDER BY V1.Contractbegin DESC .... ....如果你運行這個,你可能會看到不止一行共享最高的V1.ContractsBegin。 – Aushin
你也有一個錯字,它說「Silber」而不是「Silver」。 – Aushin
選擇top n沒有order by子句似乎是尋找麻煩的好方法。 –