2010-03-04 8 views
9

मैं एक टेबल के माध्यम से जाना चाहता हूं और कुछ डेटा यादृच्छिक रूप से मिटा देना चाहता हूं। मैं कुछ डेटा यादृच्छिक कर रहा हूं, नकली लोगों में वास्तविक नामों को बदलना आदि। अच्छी तरह से शामिल टेबलों में से एक में एक स्तंभ है जो लगभग 40% समय शून्य है। मेरा नाम यादृच्छिक ऐप उसमें कहीं भी टॉस टॉस कर सकता है जब यह नए पहले नाम निर्दिष्ट करता है। लेकिन मैं इसे अंत में करना चाहता हूं: कुछ डेटा यादृच्छिक रूप से छिड़कें।मैं पंक्तियों को यादृच्छिक रूप से कैसे अपडेट कर सकता हूं?

मैं इस कोड है, जो काम नहीं करता है, लेकिन यकीन है कि जैसे यह मेरे लिए चाहिए दिखता है:

Use MyDb 
go 

CREATE VIEW vRandNumber 
AS 
SELECT RAND() as RandNumber 

go 

CREATE FUNCTION RandNumber() 
RETURNS float 
AS 
    BEGIN 
    RETURN (SELECT RandNumber FROM vRandNumber) 
    END 

go 

select dbo.RandNumber() 

update names set nickname = null 
where ((select dbo.RandNumber()) > 0.5) 

जब मैं RandNumber समारोह यह ठीक, बहुत यादृच्छिक है चलाते हैं। लेकिन जब मैं अद्यतन करता हूं तो यह आधे समय की सभी पंक्तियों को अद्यतन करता है और समय के दूसरे भाग में पंक्तियों में से कोई भी नहीं।

मैं चाहता हूं कि जब भी मैं स्क्रिप्ट चलाता हूं, मैं इसे यादृच्छिक संख्या में पंक्तियां अपडेट करना चाहता हूं। मैंने वास्तव में सोचा था कि टेबल में प्रत्येक पंक्ति के लिए रैंडनंबर जैसे एक समारोह को एक बार चलाया जाएगा। जाहिरा तौर पर नहीं।

क्या यह लूप के बिना और कंसोल ऐप के बिना संभव है?

संपादित करें: मैंने इसे सीधे (जहां) के कुछ भिन्नताओं के साथ भी कोशिश की और उसी परिणाम प्राप्त किए।

+1

आप केवल इसका उपयोग कर सकते हैं: 'कहां रैंड()> 0.5'। दृश्य और कार्य की कोई आवश्यकता नहीं है। –

+0

@OMG: कोशिश की, वही परिणाम। – jcollum

+0

10k विचार, 7 अपवॉट्स; smh – jcollum

उत्तर

22

मानते हुए अपने नाम तालिका क्रमांक नामक एक प्राथमिक कुंजी क्षेत्र है, इस पंक्तियों की एक यादृच्छिक 50 प्रतिशत में उपनाम रद्द होगा:

update dbo.Names set Nickname = null where Id in 
(
    select top 50 percent id from dbo.Names order by NEWID() 
) 
+0

यह काम करता है लेकिन अक्षम है - प्रत्येक पंक्ति के लिए एक नया GUID उत्पन्न करने में पंक्ति के लिए एक पूर्णांक उत्पन्न करने में कुछ समय लगेगा। –

+7

पीएफटी, चलो! सुपर प्रदर्शन वास्तव में इस तरह के उपयोग के मामले के लिए एक मुद्दा है? समयपूर्व अनुकूलन के बारे में बात करें। मैंने 182,770 पंक्तियों के साथ एक तालिका पर इस दृष्टिकोण की कोशिश की है और यह 11 सेकंड में चला। –

+0

अच्छा, यह करीब है। लेकिन यह हमेशा पंक्तियों की एक ही संख्या को अद्यतन करेगा। मुझे लगता है कि मुझे पंक्तियों की यादृच्छिक संख्या अपडेट करने के लिए लूप की आवश्यकता है। – jcollum

1

RandNumber एक समारोह है। एसक्यूएल में कार्यों को एक ही इनपुट के लिए हर बार एक ही परिणाम आउटपुट करना चाहिए, जब तक कि अंतर्निहित डेटाबेस डेटा बदल नहीं जाता है। यह एक फ़ंक्शन की गणितीय परिभाषा है (जैसा कि एक सामान्य प्रोग्रामिंग भाषा एक "फ़ंक्शन" का इलाज करती है, जो एक फ़ंक्शन-जैसी निर्माण का अधिक है)।

चूंकि आपके फ़ंक्शन के परिणाम को अपडेट स्टेटमेंट (जो परमाणु ऑपरेशन है) के दौरान कभी भी नहीं बदला जाना चाहिए, आपकी क्वेरी के लिए क्वेरी प्लान कंपाइलर केवल RandNumber पर कॉल करता है और फिर परिणाम को कैश करता है।

आप सीधे अपनी क्वेरी में RAND का संदर्भ देने में सक्षम हो सकते हैं, लेकिन यदि यह अभी भी काम नहीं करता है, तो आपको इसे संग्रहीत प्रक्रिया में तुरंत करना होगा।

+0

ठीक है, लेकिन मैंने सुना है कि जब आप एक चुनिंदा() के चयन के रूप में getdate() को चुनते हैं तो getdate() चयन में प्रत्येक पंक्ति के लिए एक बार चलाएगा। क्या यह सही नहीं है? – jcollum

+3

एमएस-एसक्यूएल फ़ंक्शंस में निर्धारिती (जैसा कि आपने वर्णन किया है) या गैर-निर्धारिती देखें http://msdn.microsoft.com/en-us/library/aa214775%28SQL.80%29.aspx रैंड फ़ंक्शन गैर निर्धारक नहीं है । –

+0

इस मामले में, लगभग हर कार्य निश्चित रूप से चलाया जाएगा क्योंकि 'अद्यतन' परमाणु है। इसलिए, यहां तक ​​कि यदि एक सामान्य रूप से गैर-निर्धारिती कार्य कहा जाता है, तो इसकी स्कीमा-बाध्य प्रकृति इस तथ्य से अस्वीकार कर दी जाती है कि क्वेरी निष्पादन के दौरान अंतर्निहित डेटा नहीं बदला जा सकता है। मुझे लगता है कि ** ** को तब तक किया जाना चाहिए जब तक कि आप कार्य योजना कंपाइलर को इस तथ्य के बावजूद गैर-निर्धारिती के रूप में कार्य करने के लिए मजबूर नहीं कर सकते कि यह ऐसा नहीं करना चाहेंगे। –

0

के बारे में

update names set nickname = null 
where abs(checksum(nickname) % 2) = 0 
+0

नहीं, मैंने आपके स्थान के साथ अपडेट चलाया और जब भी मैंने इसे चलाया तो सभी पंक्तियों को अपडेट किया गया। – jcollum

+0

@jcollumn, अजीब/यहां तक ​​कि कोई भी कैसे करता है? – Hogan

+0

@jcollumn - ठीक है मैंने इसका परीक्षण किया, यह काम करेगा ... चेतावनी शून्य नाम या "निरंतर" नाम सभी एक ही काम करेंगे, इसलिए यह पूरी तरह से यादृच्छिक नहीं है। – Hogan

0

कुछ इस तरह की कोशिश कैसे:

WHERE DATEPART(ms,CreateDate)>500 

जहां "CreateDate" उस में एक वास्तविक तारीख और समय है कि तालिका में पहले से ही एक स्तंभ है।Tthe मिलीसेकंड काफी यादृच्छिक होना चाहिए

संपादित यहाँ एक और तरीका है:

DECLARE @YourTable table (RowID int, RowValue varchar(5)) 
INSERT INTO @YourTable VALUES (1,'one') 
INSERT INTO @YourTable VALUES (2,'two') 
INSERT INTO @YourTable VALUES (3,'three') 

SELECT 
    RAND(row_number() over(order by RowID)+DATEPART(ms,GETDATE())),* 
    FROM @YourTable 

आउटपुट रन 1:

     RowID  RowValue 
---------------------- ----------- -------- 
0.716200609189072  1   one 
0.71621924216033  2   two 
0.716237875131588  3   three 

(3 पंक्ति (यों) प्रभावित)

आउटपुट रन 2:

     RowID  RowValue 
---------------------- ----------- -------- 
0.727007732518828  1   one 
0.727026365490086  2   two 
0.727044998461344  3   three 

(3 row(s) affected) 
0

RAND() (और GetDate/CURRENT_TIMESTAMP) एक बार प्रति मूल्यांकन किया जाता है बयान। आपको इसके चारों ओर जाने के लिए कुछ रास्ता चाहिए। एक तरीका यह है (यदि आपके पास सुविधाजनक पंक्ति मूल्यवान पूर्णांक है, उदाहरण के लिए आईडी कॉलम), तो इसके बजाय रैंड (आईडी) को कॉल करना है।

+0

अभी भी केवल एक बार बुलाया जाता है। – Hogan

+0

उम, नहीं। रैंड (आईडी), जहां आईडी प्रति पंक्ति आधार पर भिन्न होती है, को प्रति पंक्ति एक बार कहा जाता है। –

0

RAND() एक प्रश्न के भीतर जारी रहता है।

SELECT RAND() 
FROM names 

आपको बराबर संख्याओं का एक सेट देगा।

आप कुछ इस तरह करने की जरूरत है:

WITH q AS 
     (
     SELECT *, 
       ABS(CHECKSUM(NEWID())) % 2 AS r 
     FROM names 
     ) 
UPDATE q 
SET  nickname = NULL 
WHERE r = 0 
0

यह सामान्य वितरण (यादृच्छिक नहीं) समाधान है। यह Vehicle.ID % 10 + 1 = branch_number के अनुसार शाखाओं को वाहनों को आवंटित करता है:

; WITH mytbl AS (
    SELECT TOP 10 *, ROW_NUMBER() OVER (ORDER BY NEWID()) num 
    FROM Branch 
    ORDER BY num 
) 

UPDATE v 
SET BranchID = mytbl.ID 
FROM Vehicle v 
    INNER JOIN mytbl ON mytbl.num = v.ID % 10 + 1 

SELECT BranchID, COUNT(*) FROM Vehicle GROUP BY BranchID 
संबंधित मुद्दे

 संबंधित मुद्दे