我有一個表與產品價值如下:反向串
蘋果iPhone
蘋果iPhone
三星手機
手機三星
我想刪除這是完全相反的(我認爲他們爲重複)表的那些產品,從而代替4條記錄,我的表只需要2個記錄
蘋果iPhone
三星手機
我明白,有在SQL Server REVERSE功能,但它會扭轉整個字符串,它不是我要找的。
我非常感謝任何建議/想法。
我有一個表與產品價值如下:反向串
蘋果iPhone
蘋果iPhone
三星手機
手機三星
我想刪除這是完全相反的(我認爲他們爲重複)表的那些產品,從而代替4條記錄,我的表只需要2個記錄
蘋果iPhone
三星手機
我明白,有在SQL Server REVERSE功能,但它會扭轉整個字符串,它不是我要找的。
我非常感謝任何建議/想法。
假設你的字典裏沒有包含任何XML實體(例如>
或<
),並且它是不實際手動創建一堆UPDATE
語句爲表中單詞的每個組合(如果是實用,那麼簡化你的生活,不要讀這個答案,並使用Justin's answer),你可以創建這樣的功能:
CREATE FUNCTION dbo.SplitSafeStrings
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(SELECT Item = LTRIM(RTRIM(y.i.value('(./text())[1]', 'nvarchar(4000)')))
FROM (SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>') + '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i));
GO
(如果XML是一個問題,there are other, more complex alternatives,如CLR)
然後,你可以這樣做:
DECLARE @x TABLE(id INT IDENTITY(1,1), s VARCHAR(64));
INSERT @x(s) VALUES
('apple iphone'),
('iphone Apple'),
('iphone samsung hoochie blat'),
('samsung hoochie blat iphone');
;WITH cte1 AS
(
SELECT id, Item FROM @x AS x
CROSS APPLY dbo.SplitSafeStrings(LOWER(x.s), ' ') AS y
),
cte2(id,words) AS
(
SELECT DISTINCT id, STUFF((SELECT ',' + orig.Item
FROM cte1 AS orig
WHERE orig.id = cte1.id
ORDER BY orig.Item
FOR XML PATH(''), TYPE).value('.[1]','nvarchar(max)'),1,1,'')
FROM cte1
),
cte3 AS
(
SELECT id, words, rn = ROW_NUMBER() OVER (PARTITION BY words ORDER BY id)
FROM cte2
)
SELECT id, words, rn FROM cte3
-- WHERE rn = 1 -- rows to keep
-- WHERE rn > 1 -- rows to delete
;
所以你可以,三個熱膨脹係數之後,而不是在上述最後SELECT
,說:
DELETE t FROM @x AS t
INNER JOIN cte3 ON cte3.id = t.id
WHERE cte3.rn > 1;
什麼應該留在@x
?
SELECT id, s FROM @x;
結果:
id s
-- ---------------------------
1 apple iphone
3 iphone samsung hoochie blat
在我看來,你是這個複雜的太多,簡單的更新語句將工作:
UPDATE table SET productname = 'apple iphone' WHERE productname = 'iphone apple'
這假設你知道所有可能的組合,並且寫所有這些命令並不是太乏味(如果有成千上萬的話呢?)也應該是'= 'apple iphone' - 單引號是T-SQL中的雙引號的字符串分隔符es不是。順便說一句,當你的答案剛好是3秒鐘時,你是如何進行加票的? –
@AaronBertrand我向上投票。從開始就有單引號。 – Renan
首先,是的,它假設。其次,你是正確的,固定的。第三,我不知道 –
我不知道如何在SQL做到這一點,但在語言,你用接口SQL,你可以這樣做:
你可以標記每行,以便你有一個單詞的數組,使「iphone蘋果」變成{「iphone」,「蘋果」},然後你可以切換順序元素使用一個通用的交換語句,以便它變成{「apple」,「iphone」},然後您可以將其重新變成一個字符串以製作「apple iphone」
雖然我上面描述的過程是不是所有的很難做到,找出哪些是彼此的複製品(知道翻轉哪些)可能是一個困難的問題上的數據實例
築底你已經前提是您可以嘗試如下所示:
如果productname的「正確」格式爲<brand> <product_type>
,則可以刪除產品名稱爲not like '<brand>%'
的所有產品。
以上情況不會有幫助 - 是否有任何產品命名規則?
如上理念不能應用,創建Split
功能:
CREATE FUNCTION [dbo].[Split]
(
@String NVARCHAR(4000),
@Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)- stpos)
FROM Split
)
而且在查詢中使用它:
select
(SELECT (', ' + Data)
FROM Split(t.textVal, ' ')
order by [Data]
FOR XML PATH('')
)
from
test t
這將爲您提供與排序的話產品名稱。有了這個,你可以很容易地找到重複。 第二個查詢是粗糙的邊緣,因爲我必須去afk,但你應該設法平滑它:) 祝你好運
這裏沒有產品命名規則,其他一些例子可以是:「online nokia lumia shop」,「shop lumia nokia online」 – pk188
這裏是一個解決方案的兩個或兩個以上的單詞用空格分開。基本上這個想法是使用遞歸CTE按空間拆分,然後爲xml將名稱放回到一起排序。然後,您可以通過新的名稱列組,讓您解除複製列表:
with split as (
select id,
convert(varchar(max), left(name, charindex(' ', name + ' ') - 1)) word,
stuff(name, 1, charindex(' ', name + ' '), '') name
from products
union all
select id,
convert(varchar(max), left(name, charindex(' ', name + ' ') - 1)) word,
stuff(name, 1, charindex(' ', name + ' '), '') name
from split where name > ''
),
hom as (
select id,
(select word + ' '
from split where id=o.id
order by word for xml path('')) name
from split o
)
select name, min(id) id from hom group by name
如果你添加第三個字(OP已經指出),你的SQLfiddle很快就會崩潰, 。 [新SQLfiddle](http://www.sqlfiddle.com/#!6/7dd16/1) –
2個或更多字的解決方案將涉及一個表值函數..只需一秒 – gordy
有沒有永遠只兩個字? –
也可以有兩個以上的單詞。 – pk188
我知道你打電話給iPhone的時候,因爲蘋果只有一個品牌......但是不得不支持Galaxy S/Y/II/III/IV/Grand Duos/Grand Quattro/Win/Note/Note 2/Tab/Tab 2 7.0「,我認爲」三星手機「以相同的名稱呼叫很多不同的東西...... – Renan