यदि आपको अपने वातावरण में सीएलआर का उपयोग करने की अनुमति है, तो यह उपयोगकर्ता द्वारा परिभाषित कुल के लिए एक दर्जी मामला है।
विशेष रूप से, यह संभवतः जाने का तरीका है यदि स्रोत डेटा गैर-तुच्छ रूप से बड़ा है और / या आपको अपने आवेदन में इस प्रकार की बहुत कुछ करने की आवश्यकता है। मुझे दृढ़ता से संदेह है कि हारून के समाधान के लिए क्वेरी योजना अच्छी तरह से स्केल नहीं होगी क्योंकि इनपुट आकार बढ़ता है। (मैंने अस्थायी तालिका में एक इंडेक्स जोड़ने की कोशिश की, लेकिन इससे कोई मदद नहीं मिली।)
यह समाधान, कई अन्य चीजों की तरह, एक व्यापार है:
- आपके या आपके ग्राहक के वातावरण में CLR एकीकरण का उपयोग करने के लिए राजनीति / नीति।
- सीएलआर फ़ंक्शन तेजी से होने की संभावना है, और डेटा के एक वास्तविक सेट को बेहतर ढंग से मापेंगे।
- सीएलआर फ़ंक्शन अन्य प्रश्नों में पुन: प्रयोज्य होगा, और आपको हर बार इस प्रकार की चीज़ करने के लिए एक जटिल उपकुंजी की नकल (और डिबग) नहीं करनी होगी।
- स्ट्रेट टी-एसक्यूएल बाहरी कोड के एक टुकड़े को लिखने और प्रबंधित करने की तुलना में सरल है।
- शायद आप नहीं जानते कि कैसे C # या VB में प्रोग्राम करें।
- आदि।
संपादित करें: ठीक है, मैं यह देखने की कोशिश करने के लिए गया था कि क्या यह वास्तव में बेहतर था, और यह इस आवश्यकता को दर्शाता है कि टिप्पणी एक विशिष्ट क्रम में हो सकती है वर्तमान में एक समुच्चय फ़ंक्शन का उपयोग करके संतुष्ट करना संभव नहीं है। :(
SqlUserDefinedAggregateAttribute.IsInvariantToOrder देखें । मूल रूप से, आपको जो करने की आवश्यकता है वह है, OVER(PARTITION BY customer_code ORDER BY row_num)
लेकिन समुच्चय करते समय खंड ORDER BY
में समर्थित नहीं है OVER
। मैं मान रहा हूं कि SQL सर्वर में इस कार्यक्षमता को जोड़ने से कीड़े का एक कैन खुल जाता है, क्योंकि निष्पादन योजना में जो बदलाव करने की आवश्यकता होती है वह तुच्छ है। उपरोक्त लिंक का कहना है कि यह भविष्य के उपयोग के लिए आरक्षित है, इसलिए इसे भविष्य में लागू किया जा सकता है (2005 में आप शायद भाग्य से बाहर हैं, हालांकि)।
यह हो सकता है अभी भी पैकिंग और पार्स करने द्वारा पूरा किया जा row_num
एकत्रित किया स्ट्रिंग में मूल्य, और उसके बाद प्रकार CLR वस्तु के भीतर ... जो सुंदर hackish लगता है कर।
किसी भी घटना में, नीचे दिया गया कोड मैं किसी और के उपयोग की स्थिति में भी इसे उपयोगी पाता है। मैं पाठक के लिए एक अभ्यास के रूप में हैकिंग भाग को छोड़ दूँगा। ध्यान दें कि मैंने परीक्षण डेटा के लिए एडवेंचरवर्क्स (2005) का उपयोग किया था।
एकत्रित विधानसभा:
using System;
using System.IO;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
namespace MyCompany.SqlServer
{
[Serializable]
[SqlUserDefinedAggregate
(
Format.UserDefined,
IsNullIfEmpty = false,
IsInvariantToDuplicates = false,
IsInvariantToNulls = true,
IsInvariantToOrder = false,
MaxByteSize = -1
)]
public class StringConcatAggregate : IBinarySerialize
{
private string _accum;
private bool _isEmpty;
public void Init()
{
_accum = string.Empty;
_isEmpty = true;
}
public void Accumulate(SqlString value)
{
if (!value.IsNull)
{
if (!_isEmpty)
_accum += ' ';
else
_isEmpty = false;
_accum += value.Value;
}
}
public void Merge(StringConcatAggregate value)
{
Accumulate(value.Terminate());
}
public SqlString Terminate()
{
return new SqlString(_accum);
}
public void Read(BinaryReader r)
{
this.Init();
_accum = r.ReadString();
_isEmpty = _accum.Length == 0;
}
public void Write(BinaryWriter w)
{
w.Write(_accum);
}
}
}
परीक्षण के लिए टी-एसक्यूएल ( CREATE ASSEMBLY
और sp_configure
सीएलआर को सक्षम करने के लिए):
CREATE TABLE [dbo].[Comments]
(
CustomerCode int NOT NULL,
RowNum int NOT NULL,
Comments nvarchar(25) NOT NULL
)
INSERT INTO [dbo].[Comments](CustomerCode, RowNum, Comments)
SELECT
DENSE_RANK() OVER(ORDER BY FirstName),
ROW_NUMBER() OVER(PARTITION BY FirstName ORDER BY ContactID),
Phone
FROM [AdventureWorks].[Person].[Contact]
GO
CREATE AGGREGATE [dbo].[StringConcatAggregate]
(
@input nvarchar(MAX)
)
RETURNS nvarchar(MAX)
EXTERNAL NAME StringConcatAggregate.[MyCompany.SqlServer.StringConcatAggregate]
GO
SELECT
CustomerCode,
[dbo].[StringConcatAggregate](Comments) AS AllComments
FROM [dbo].[Comments]
GROUP BY CustomerCode